| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| # file Copyright.txt or https://cmake.org/licensing for details. | |
| #[=======================================================================[.rst: | |
| FindMPI | |
| ------- | |
| Find a Message Passing Interface (MPI) implementation. | |
| The Message Passing Interface (MPI) is a library used to write | |
| high-performance distributed-memory parallel applications, and is | |
| typically deployed on a cluster. MPI is a standard interface (defined | |
| by the MPI forum) for which many implementations are available. | |
| .. versionadded:: 3.10 | |
| Major overhaul of the module: many new variables, per-language components, | |
| support for a wider variety of runtimes. | |
| Variables for using MPI | |
| ^^^^^^^^^^^^^^^^^^^^^^^ | |
| The module exposes the components ``C``, ``CXX``, ``MPICXX`` and ``Fortran``. | |
| Each of these controls the various MPI languages to search for. | |
| The difference between ``CXX`` and ``MPICXX`` is that ``CXX`` refers to the | |
| MPI C API being usable from C++, whereas ``MPICXX`` refers to the MPI-2 C++ API | |
| that was removed again in MPI-3. | |
| Depending on the enabled components the following variables will be set: | |
| ``MPI_FOUND`` | |
| Variable indicating that MPI settings for all requested languages have been found. | |
| If no components are specified, this is true if MPI settings for all enabled languages | |
| were detected. Note that the ``MPICXX`` component does not affect this variable. | |
| ``MPI_VERSION`` | |
| Minimal version of MPI detected among the requested languages, or all enabled languages | |
| if no components were specified. | |
| This module will set the following variables per language in your | |
| project, where ``<lang>`` is one of C, CXX, or Fortran: | |
| ``MPI_<lang>_FOUND`` | |
| Variable indicating the MPI settings for ``<lang>`` were found and that | |
| simple MPI test programs compile with the provided settings. | |
| ``MPI_<lang>_COMPILER`` | |
| MPI compiler for ``<lang>`` if such a program exists. | |
| ``MPI_<lang>_COMPILE_OPTIONS`` | |
| Compilation options for MPI programs in ``<lang>``, given as a :ref:`;-list <CMake Language Lists>`. | |
| ``MPI_<lang>_COMPILE_DEFINITIONS`` | |
| Compilation definitions for MPI programs in ``<lang>``, given as a :ref:`;-list <CMake Language Lists>`. | |
| ``MPI_<lang>_INCLUDE_DIRS`` | |
| Include path(s) for MPI header. | |
| ``MPI_<lang>_LINK_FLAGS`` | |
| Linker flags for MPI programs. | |
| ``MPI_<lang>_LIBRARIES`` | |
| All libraries to link MPI programs against. | |
| .. versionadded:: 3.9 | |
| Additionally, the following :prop_tgt:`IMPORTED` targets are defined: | |
| ``MPI::MPI_<lang>`` | |
| Target for using MPI from ``<lang>``. | |
| The following variables indicating which bindings are present will be defined: | |
| ``MPI_MPICXX_FOUND`` | |
| Variable indicating whether the MPI-2 C++ bindings are present (introduced in MPI-2, removed with MPI-3). | |
| ``MPI_Fortran_HAVE_F77_HEADER`` | |
| True if the Fortran 77 header ``mpif.h`` is available. | |
| ``MPI_Fortran_HAVE_F90_MODULE`` | |
| True if the Fortran 90 module ``mpi`` can be used for accessing MPI (MPI-2 and higher only). | |
| ``MPI_Fortran_HAVE_F08_MODULE`` | |
| True if the Fortran 2008 ``mpi_f08`` is available to MPI programs (MPI-3 and higher only). | |
| If possible, the MPI version will be determined by this module. The facilities to detect the MPI version | |
| were introduced with MPI-1.2, and therefore cannot be found for older MPI versions. | |
| ``MPI_<lang>_VERSION_MAJOR`` | |
| Major version of MPI implemented for ``<lang>`` by the MPI distribution. | |
| ``MPI_<lang>_VERSION_MINOR`` | |
| Minor version of MPI implemented for ``<lang>`` by the MPI distribution. | |
| ``MPI_<lang>_VERSION`` | |
| MPI version implemented for ``<lang>`` by the MPI distribution. | |
| Note that there's no variable for the C bindings being accessible through ``mpi.h``, since the MPI standards | |
| always have required this binding to work in both C and C++ code. | |
| For running MPI programs, the module sets the following variables | |
| ``MPIEXEC_EXECUTABLE`` | |
| Executable for running MPI programs, if such exists. | |
| ``MPIEXEC_NUMPROC_FLAG`` | |
| Flag to pass to ``mpiexec`` before giving it the number of processors to run on. | |
| ``MPIEXEC_MAX_NUMPROCS`` | |
| Number of MPI processors to utilize. Defaults to the number | |
| of processors detected on the host system. | |
| ``MPIEXEC_PREFLAGS`` | |
| Flags to pass to ``mpiexec`` directly before the executable to run. | |
| ``MPIEXEC_POSTFLAGS`` | |
| Flags to pass to ``mpiexec`` after other flags. | |
| Variables for locating MPI | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| This module performs a four step search for an MPI implementation: | |
| 1. Search for ``MPIEXEC_EXECUTABLE`` and, if found, use its base directory. | |
| 2. Check if the compiler has MPI support built-in. This is the case if the user passed a | |
| compiler wrapper as ``CMAKE_<LANG>_COMPILER`` or if they use Cray system compiler wrappers. | |
| 3. Attempt to find an MPI compiler wrapper and determine the compiler information from it. | |
| 4. Try to find an MPI implementation that does not ship such a wrapper by guessing settings. | |
| Currently, only Microsoft MPI and MPICH2 on Windows are supported. | |
| For controlling the ``MPIEXEC_EXECUTABLE`` step, the following variables may be set: | |
| ``MPIEXEC_EXECUTABLE`` | |
| Manually specify the location of ``mpiexec``. | |
| ``MPI_HOME`` | |
| Specify the base directory of the MPI installation. | |
| ``ENV{MPI_HOME}`` | |
| Environment variable to specify the base directory of the MPI installation. | |
| ``ENV{I_MPI_ROOT}`` | |
| Environment variable to specify the base directory of the MPI installation. | |
| For controlling the compiler wrapper step, the following variables may be set: | |
| ``MPI_<lang>_COMPILER`` | |
| Search for the specified compiler wrapper and use it. | |
| ``MPI_<lang>_COMPILER_FLAGS`` | |
| Flags to pass to the MPI compiler wrapper during interrogation. Some compiler wrappers | |
| support linking debug or tracing libraries if a specific flag is passed and this variable | |
| may be used to obtain them. | |
| ``MPI_COMPILER_FLAGS`` | |
| Used to initialize ``MPI_<lang>_COMPILER_FLAGS`` if no language specific flag has been given. | |
| Empty by default. | |
| ``MPI_EXECUTABLE_SUFFIX`` | |
| A suffix which is appended to all names that are being looked for. For instance you may set this | |
| to ``.mpich`` or ``.openmpi`` to prefer the one or the other on Debian and its derivatives. | |
| In order to control the guessing step, the following variable may be set: | |
| ``MPI_GUESS_LIBRARY_NAME`` | |
| Valid values are ``MSMPI`` and ``MPICH2``. If set, only the given library will be searched for. | |
| By default, ``MSMPI`` will be preferred over ``MPICH2`` if both are available. | |
| This also sets ``MPI_SKIP_COMPILER_WRAPPER`` to ``true``, which may be overridden. | |
| Each of the search steps may be skipped with the following control variables: | |
| ``MPI_ASSUME_NO_BUILTIN_MPI`` | |
| If true, the module assumes that the compiler itself does not provide an MPI implementation and | |
| skips to step 2. | |
| ``MPI_SKIP_COMPILER_WRAPPER`` | |
| If true, no compiler wrapper will be searched for. | |
| ``MPI_SKIP_GUESSING`` | |
| If true, the guessing step will be skipped. | |
| Additionally, the following control variable is available to change search behavior: | |
| ``MPI_CXX_SKIP_MPICXX`` | |
| Add some definitions that will disable the MPI-2 C++ bindings. | |
| Currently supported are MPICH, Open MPI, Platform MPI and derivatives thereof, | |
| for example MVAPICH or Intel MPI. | |
| If the find procedure fails for a variable ``MPI_<lang>_WORKS``, then the settings detected by or passed to | |
| the module did not work and even a simple MPI test program failed to compile. | |
| If all of these parameters were not sufficient to find the right MPI implementation, a user may | |
| disable the entire autodetection process by specifying both a list of libraries in ``MPI_<lang>_LIBRARIES`` | |
| and a list of include directories in ``MPI_<lang>_ADDITIONAL_INCLUDE_DIRS``. | |
| Any other variable may be set in addition to these two. The module will then validate the MPI settings and store the | |
| settings in the cache. | |
| Cache variables for MPI | |
| ^^^^^^^^^^^^^^^^^^^^^^^ | |
| The variable ``MPI_<lang>_INCLUDE_DIRS`` will be assembled from the following variables. | |
| For C and CXX: | |
| ``MPI_<lang>_HEADER_DIR`` | |
| Location of the ``mpi.h`` header on disk. | |
| For Fortran: | |
| ``MPI_Fortran_F77_HEADER_DIR`` | |
| Location of the Fortran 77 header ``mpif.h``, if it exists. | |
| ``MPI_Fortran_MODULE_DIR`` | |
| Location of the ``mpi`` or ``mpi_f08`` modules, if available. | |
| For all languages the following variables are additionally considered: | |
| ``MPI_<lang>_ADDITIONAL_INCLUDE_DIRS`` | |
| A :ref:`;-list <CMake Language Lists>` of paths needed in addition to the normal include directories. | |
| ``MPI_<include_name>_INCLUDE_DIR`` | |
| Path variables for include folders referred to by ``<include_name>``. | |
| ``MPI_<lang>_ADDITIONAL_INCLUDE_VARS`` | |
| A :ref:`;-list <CMake Language Lists>` of ``<include_name>`` that will be added to the include locations of ``<lang>``. | |
| The variable ``MPI_<lang>_LIBRARIES`` will be assembled from the following variables: | |
| ``MPI_<lib_name>_LIBRARY`` | |
| The location of a library called ``<lib_name>`` for use with MPI. | |
| ``MPI_<lang>_LIB_NAMES`` | |
| A :ref:`;-list <CMake Language Lists>` of ``<lib_name>`` that will be added to the include locations of ``<lang>``. | |
| Usage of mpiexec | |
| ^^^^^^^^^^^^^^^^ | |
| When using ``MPIEXEC_EXECUTABLE`` to execute MPI applications, you should typically | |
| use all of the ``MPIEXEC_EXECUTABLE`` flags as follows: | |
| :: | |
| ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${MPIEXEC_MAX_NUMPROCS} | |
| ${MPIEXEC_PREFLAGS} EXECUTABLE ${MPIEXEC_POSTFLAGS} ARGS | |
| where ``EXECUTABLE`` is the MPI program, and ``ARGS`` are the arguments to | |
| pass to the MPI program. | |
| Advanced variables for using MPI | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| The module can perform some advanced feature detections upon explicit request. | |
| **Important notice:** The following checks cannot be performed without *executing* an MPI test program. | |
| Consider the special considerations for the behavior of :command:`try_run` during cross compilation. | |
| Moreover, running an MPI program can cause additional issues, like a firewall notification on some systems. | |
| You should only enable these detections if you absolutely need the information. | |
| If the following variables are set to true, the respective search will be performed: | |
| ``MPI_DETERMINE_Fortran_CAPABILITIES`` | |
| Determine for all available Fortran bindings what the values of ``MPI_SUBARRAYS_SUPPORTED`` and | |
| ``MPI_ASYNC_PROTECTS_NONBLOCKING`` are and make their values available as ``MPI_Fortran_<binding>_SUBARRAYS`` | |
| and ``MPI_Fortran_<binding>_ASYNCPROT``, where ``<binding>`` is one of ``F77_HEADER``, ``F90_MODULE`` and | |
| ``F08_MODULE``. | |
| ``MPI_DETERMINE_LIBRARY_VERSION`` | |
| For each language, find the output of ``MPI_Get_library_version`` and make it available as ``MPI_<lang>_LIBRARY_VERSION_STRING``. | |
| This information is usually tied to the runtime component of an MPI implementation and might differ depending on ``<lang>``. | |
| Note that the return value is entirely implementation defined. This information might be used to identify | |
| the MPI vendor and for example pick the correct one of multiple third party binaries that matches the MPI vendor. | |
| Backward Compatibility | |
| ^^^^^^^^^^^^^^^^^^^^^^ | |
| .. deprecated:: 3.10 | |
| For backward compatibility with older versions of FindMPI, these | |
| variables are set: | |
| :: | |
| MPI_COMPILER MPI_LIBRARY MPI_EXTRA_LIBRARY | |
| MPI_COMPILE_FLAGS MPI_INCLUDE_PATH MPI_LINK_FLAGS | |
| MPI_LIBRARIES | |
| In new projects, please use the ``MPI_<lang>_XXX`` equivalents. | |
| Additionally, the following variables are deprecated: | |
| ``MPI_<lang>_COMPILE_FLAGS`` | |
| Use ``MPI_<lang>_COMPILE_OPTIONS`` and ``MPI_<lang>_COMPILE_DEFINITIONS`` instead. | |
| ``MPI_<lang>_INCLUDE_PATH`` | |
| For consumption use ``MPI_<lang>_INCLUDE_DIRS`` and for specifying folders use ``MPI_<lang>_ADDITIONAL_INCLUDE_DIRS`` instead. | |
| ``MPIEXEC`` | |
| Use ``MPIEXEC_EXECUTABLE`` instead. | |
| #]=======================================================================] | |
| cmake_policy(PUSH) | |
| cmake_policy(SET CMP0057 NEW) # if IN_LIST | |
| include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) | |
| find_package(PkgConfig QUIET) | |
| # Generic compiler names | |
| set(_MPI_C_GENERIC_COMPILER_NAMES mpicc mpcc mpicc_r mpcc_r) | |
| set(_MPI_CXX_GENERIC_COMPILER_NAMES mpicxx mpiCC mpcxx mpCC mpic++ mpc++ | |
| mpicxx_r mpiCC_r mpcxx_r mpCC_r mpic++_r mpc++_r) | |
| set(_MPI_Fortran_GENERIC_COMPILER_NAMES mpif95 mpif95_r mpf95 mpf95_r | |
| mpif90 mpif90_r mpf90 mpf90_r | |
| mpif77 mpif77_r mpf77 mpf77_r | |
| mpifc) | |
| #Fujitsu cross/own compiler names | |
| set(_MPI_Fujitsu_C_COMPILER_NAMES mpifccpx mpifcc) | |
| set(_MPI_Fujitsu_CXX_COMPILER_NAMES mpiFCCpx mpiFCC) | |
| set(_MPI_Fujitsu_Fortran_COMPILER_NAMES mpifrtpx mpifrt) | |
| # GNU compiler names | |
| set(_MPI_GNU_C_COMPILER_NAMES mpigcc mpgcc mpigcc_r mpgcc_r) | |
| set(_MPI_GNU_CXX_COMPILER_NAMES mpig++ mpg++ mpig++_r mpg++_r mpigxx) | |
| set(_MPI_GNU_Fortran_COMPILER_NAMES mpigfortran mpgfortran mpigfortran_r mpgfortran_r | |
| mpig77 mpig77_r mpg77 mpg77_r) | |
| # Intel MPI compiler names on Windows | |
| if(WIN32) | |
| list(APPEND _MPI_C_GENERIC_COMPILER_NAMES mpicc.bat) | |
| list(APPEND _MPI_CXX_GENERIC_COMPILER_NAMES mpicxx.bat) | |
| list(APPEND _MPI_Fortran_GENERIC_COMPILER_NAMES mpifc.bat) | |
| # Intel MPI compiler names | |
| set(_MPI_Intel_C_COMPILER_NAMES mpiicc.bat) | |
| set(_MPI_Intel_CXX_COMPILER_NAMES mpiicpc.bat) | |
| set(_MPI_Intel_Fortran_COMPILER_NAMES mpiifort.bat mpif77.bat mpif90.bat) | |
| # Intel MPI compiler names | |
| set(_MPI_IntelLLVM_C_COMPILER_NAMES mpiicc.bat) | |
| set(_MPI_IntelLLVM_CXX_COMPILER_NAMES mpiicpc.bat) | |
| set(_MPI_IntelLLVM_Fortran_COMPILER_NAMES mpiifort.bat mpif77.bat mpif90.bat) | |
| # Intel MPI compiler names for MSMPI | |
| set(_MPI_MSVC_C_COMPILER_NAMES mpicl.bat) | |
| set(_MPI_MSVC_CXX_COMPILER_NAMES mpicl.bat) | |
| else() | |
| # Intel compiler names | |
| set(_MPI_Intel_C_COMPILER_NAMES mpiicc) | |
| set(_MPI_Intel_CXX_COMPILER_NAMES mpiicpc mpiicxx mpiic++) | |
| set(_MPI_Intel_Fortran_COMPILER_NAMES mpiifort mpiif95 mpiif90 mpiif77) | |
| # Intel compiler names | |
| set(_MPI_IntelLLVM_C_COMPILER_NAMES mpiicc) | |
| set(_MPI_IntelLLVM_CXX_COMPILER_NAMES mpiicpc mpiicxx mpiic++) | |
| set(_MPI_IntelLLVM_Fortran_COMPILER_NAMES mpiifort mpiif95 mpiif90 mpiif77) | |
| endif() | |
| # PGI compiler names | |
| set(_MPI_PGI_C_COMPILER_NAMES mpipgicc mpipgcc mppgcc) | |
| set(_MPI_PGI_CXX_COMPILER_NAMES mpipgic++ mpipgCC mppgCC) | |
| set(_MPI_PGI_Fortran_COMPILER_NAMES mpipgifort mpipgf95 mpipgf90 mppgf95 mppgf90 mpipgf77 mppgf77) | |
| # XLC MPI Compiler names | |
| set(_MPI_XL_C_COMPILER_NAMES mpxlc mpxlc_r mpixlc mpixlc_r) | |
| set(_MPI_XL_CXX_COMPILER_NAMES mpixlcxx mpixlC mpixlc++ mpxlcxx mpxlc++ mpixlc++ mpxlCC | |
| mpixlcxx_r mpixlC_r mpixlc++_r mpxlcxx_r mpxlc++_r mpixlc++_r mpxlCC_r) | |
| set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95_r | |
| mpixlf90 mpixlf90_r mpxlf90 mpxlf90_r | |
| mpixlf77 mpixlf77_r mpxlf77 mpxlf77_r | |
| mpixlf mpixlf_r mpxlf mpxlf_r) | |
| # Cray Compiler names | |
| set(_MPI_Cray_C_COMPILER_NAMES cc) | |
| set(_MPI_Cray_CXX_COMPILER_NAMES CC) | |
| set(_MPI_Cray_Fortran_COMPILER_NAMES ftn) | |
| # Prepend vendor-specific compiler wrappers to the list. If we don't know the compiler, | |
| # attempt all of them. | |
| # By attempting vendor-specific compiler names first, we should avoid situations where the compiler wrapper | |
| # stems from a proprietary MPI and won't know which compiler it's being used for. For instance, Intel MPI | |
| # controls its settings via the I_MPI_CC environment variables if the generic name is being used. | |
| # If we know which compiler we're working with, we can use the most specialized wrapper there is in order to | |
| # pick up the right settings for it. | |
| foreach (LANG IN ITEMS C CXX Fortran) | |
| set(_MPI_${LANG}_COMPILER_NAMES "") | |
| foreach (id IN ITEMS Fujitsu FujitsuClang GNU Intel IntelLLVM MSVC PGI XL) | |
| if (NOT CMAKE_${LANG}_COMPILER_ID OR CMAKE_${LANG}_COMPILER_ID STREQUAL id) | |
| foreach(_COMPILER_NAME IN LISTS _MPI_${id}_${LANG}_COMPILER_NAMES) | |
| list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_COMPILER_NAME}${MPI_EXECUTABLE_SUFFIX}) | |
| endforeach() | |
| endif() | |
| unset(_MPI_${id}_${LANG}_COMPILER_NAMES) | |
| endforeach() | |
| foreach(_COMPILER_NAME IN LISTS _MPI_${LANG}_GENERIC_COMPILER_NAMES) | |
| list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_COMPILER_NAME}${MPI_EXECUTABLE_SUFFIX}) | |
| endforeach() | |
| unset(_MPI_${LANG}_GENERIC_COMPILER_NAMES) | |
| endforeach() | |
| # Names to try for mpiexec | |
| # Only mpiexec commands are guaranteed to behave as described in the standard, | |
| # mpirun commands are not covered by the standard in any way whatsoever. | |
| # lamexec is the executable for LAM/MPI, srun is for SLURM or Open MPI with SLURM support. | |
| # srun -n X <executable> is however a valid command, so it behaves 'like' mpiexec. | |
| set(_MPIEXEC_NAMES_BASE mpiexec mpiexec.hydra mpiexec.mpd mpirun lamexec srun) | |
| unset(_MPIEXEC_NAMES) | |
| foreach(_MPIEXEC_NAME IN LISTS _MPIEXEC_NAMES_BASE) | |
| list(APPEND _MPIEXEC_NAMES "${_MPIEXEC_NAME}${MPI_EXECUTABLE_SUFFIX}") | |
| endforeach() | |
| unset(_MPIEXEC_NAMES_BASE) | |
| function (_MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE) | |
| if(DEFINED MPI_${LANG}_COMPILER_FLAGS) | |
| separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_${LANG}_COMPILER_FLAGS}") | |
| else() | |
| separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_COMPILER_FLAGS}") | |
| endif() | |
| execute_process( | |
| COMMAND ${MPI_${LANG}_COMPILER} ${_MPI_COMPILER_WRAPPER_OPTIONS} ${QUERY_FLAG} | |
| OUTPUT_VARIABLE WRAPPER_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE | |
| ERROR_VARIABLE WRAPPER_OUTPUT ERROR_STRIP_TRAILING_WHITESPACE | |
| RESULT_VARIABLE WRAPPER_RETURN) | |
| # Some compiler wrappers will yield spurious zero return values, for example | |
| # Intel MPI tolerates unknown arguments and if the MPI wrappers loads a shared | |
| # library that has invalid or missing version information there would be warning | |
| # messages emitted by ld.so in the compiler output. In either case, we'll treat | |
| # the output as invalid. | |
| if("${WRAPPER_OUTPUT}" MATCHES "undefined reference|unrecognized|need to set|no version information available|command not found") | |
| set(WRAPPER_RETURN 255) | |
| endif() | |
| # Ensure that no error output might be passed upwards. | |
| if(NOT WRAPPER_RETURN EQUAL 0) | |
| unset(WRAPPER_OUTPUT) | |
| else() | |
| # Strip leading whitespace | |
| string(REGEX REPLACE "^ +" "" WRAPPER_OUTPUT "${WRAPPER_OUTPUT}") | |
| endif() | |
| set(${OUTPUT_VARIABLE} "${WRAPPER_OUTPUT}" PARENT_SCOPE) | |
| set(${RESULT_VARIABLE} "${WRAPPER_RETURN}" PARENT_SCOPE) | |
| endfunction() | |
| macro(_MPI_env_set_ifnot VAR VALUE) | |
| if(NOT DEFINED ENV{${VAR}}) | |
| set(_MPI_${VAR}_WAS_SET FALSE) | |
| set(ENV{${VAR}} ${${VALUE}}) | |
| else() | |
| set(_MPI_${VAR}_WAS_SET TRUE) | |
| endif() | |
| endmacro() | |
| macro(_MPI_env_unset_ifnot VAR) | |
| if(NOT _MPI_${VAR}_WAS_SET) | |
| unset(ENV{${VAR}}) | |
| endif() | |
| endmacro() | |
| function (_MPI_interrogate_compiler LANG) | |
| unset(MPI_COMPILE_CMDLINE) | |
| unset(MPI_LINK_CMDLINE) | |
| unset(MPI_COMPILE_OPTIONS_WORK) | |
| unset(MPI_COMPILE_DEFINITIONS_WORK) | |
| unset(MPI_INCLUDE_DIRS_WORK) | |
| unset(MPI_LINK_FLAGS_WORK) | |
| unset(MPI_LIB_NAMES_WORK) | |
| unset(MPI_LIB_FULLPATHS_WORK) | |
| # Define the MPICH and Intel MPI compiler variables to the compilers set in CMake. | |
| # It's possible to have a per-compiler configuration in these MPI implementations and | |
| # a particular MPICH derivate might check compiler interoperability. | |
| # Intel MPI in particular does this with I_MPI_CHECK_COMPILER. | |
| file(TO_NATIVE_PATH "${CMAKE_${LANG}_COMPILER}" _MPI_UNDERLAYING_COMPILER) | |
| # On Windows, the Intel MPI batch scripts can only work with filnames - Full paths will break them. | |
| # Due to the lack of other MPICH-based wrappers for Visual C++, we may treat this as default. | |
| if(MSVC) | |
| get_filename_component(_MPI_UNDERLAYING_COMPILER "${_MPI_UNDERLAYING_COMPILER}" NAME) | |
| endif() | |
| if("${LANG}" STREQUAL "C") | |
| _MPI_env_set_ifnot(I_MPI_CC _MPI_UNDERLAYING_COMPILER) | |
| _MPI_env_set_ifnot(MPICH_CC _MPI_UNDERLAYING_COMPILER) | |
| elseif("${LANG}" STREQUAL "CXX") | |
| _MPI_env_set_ifnot(I_MPI_CXX _MPI_UNDERLAYING_COMPILER) | |
| _MPI_env_set_ifnot(MPICH_CXX _MPI_UNDERLAYING_COMPILER) | |
| elseif("${LANG}" STREQUAL "Fortran") | |
| _MPI_env_set_ifnot(I_MPI_FC _MPI_UNDERLAYING_COMPILER) | |
| _MPI_env_set_ifnot(MPICH_FC _MPI_UNDERLAYING_COMPILER) | |
| _MPI_env_set_ifnot(I_MPI_F77 _MPI_UNDERLAYING_COMPILER) | |
| _MPI_env_set_ifnot(MPICH_F77 _MPI_UNDERLAYING_COMPILER) | |
| _MPI_env_set_ifnot(I_MPI_F90 _MPI_UNDERLAYING_COMPILER) | |
| _MPI_env_set_ifnot(MPICH_F90 _MPI_UNDERLAYING_COMPILER) | |
| endif() | |
| # Set these two variables for Intel MPI: | |
| # - I_MPI_DEBUG_INFO_STRIP: It adds 'objcopy' lines to the compiler output. We support stripping them | |
| # (see below), but if we can avoid them in the first place, we should. | |
| # - I_MPI_FORT_BIND: By default Intel MPI makes the C/C++ compiler wrappers link Fortran bindings. | |
| # This is so that mixed-language code doesn't require additional libraries when linking with mpicc. | |
| # For our purposes, this makes little sense, since correct MPI usage from CMake already circumvenes this. | |
| set(_MPI_ENV_VALUE "disable") | |
| _MPI_env_set_ifnot(I_MPI_DEBUG_INFO_STRIP _MPI_ENV_VALUE) | |
| _MPI_env_set_ifnot(I_MPI_FORT_BIND _MPI_ENV_VALUE) | |
| # 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. | |
| # Open MPI also supports -show, but separates linker and compiler information | |
| _MPI_check_compiler(${LANG} "-showme:compile" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) | |
| if (MPI_COMPILER_RETURN EQUAL 0) | |
| _MPI_check_compiler(${LANG} "-showme:link" MPI_LINK_CMDLINE MPI_COMPILER_RETURN) | |
| if (NOT MPI_COMPILER_RETURN EQUAL 0) | |
| unset(MPI_COMPILE_CMDLINE) | |
| endif() | |
| endif() | |
| # MPICH and MVAPICH offer -compile-info and -link-info. | |
| # For modern versions, both do the same as -show. However, for old versions, they do differ | |
| # when called for mpicxx and mpif90 and it's necessary to use them over -show in order to find the | |
| # removed MPI C++ bindings. | |
| if (NOT MPI_COMPILER_RETURN EQUAL 0) | |
| _MPI_check_compiler(${LANG} "-compile-info" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) | |
| if (MPI_COMPILER_RETURN EQUAL 0) | |
| _MPI_check_compiler(${LANG} "-link-info" MPI_LINK_CMDLINE MPI_COMPILER_RETURN) | |
| if (NOT MPI_COMPILER_RETURN EQUAL 0) | |
| unset(MPI_COMPILE_CMDLINE) | |
| endif() | |
| endif() | |
| endif() | |
| # Cray compiler wrappers come usually without a separate mpicc/c++/ftn, but offer | |
| # --cray-print-opts=... | |
| if (NOT MPI_COMPILER_RETURN EQUAL 0) | |
| _MPI_check_compiler(${LANG} "--cray-print-opts=cflags" | |
| MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) | |
| if (MPI_COMPILER_RETURN EQUAL 0) | |
| # Pass --no-as-needed so the mpi library is always linked. Otherwise, the | |
| # Cray compiler wrapper puts an --as-needed flag around the mpi library, | |
| # and it is not linked unless code directly refers to it. | |
| _MPI_check_compiler(${LANG} "--no-as-needed;--cray-print-opts=libs" | |
| MPI_LINK_CMDLINE MPI_COMPILER_RETURN) | |
| if (NOT MPI_COMPILER_RETURN EQUAL 0) | |
| unset(MPI_COMPILE_CMDLINE) | |
| unset(MPI_LINK_CMDLINE) | |
| endif() | |
| endif() | |
| endif() | |
| # MPICH, MVAPICH2 and Intel MPI just use "-show". Open MPI also offers this, but the | |
| # -showme commands are more specialized. | |
| if (NOT MPI_COMPILER_RETURN EQUAL 0) | |
| _MPI_check_compiler(${LANG} "-show" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) | |
| endif() | |
| # Older versions of LAM/MPI have "-showme". Open MPI also supports this. | |
| # Unknown to MPICH, MVAPICH and Intel MPI. | |
| if (NOT MPI_COMPILER_RETURN EQUAL 0) | |
| _MPI_check_compiler(${LANG} "-showme" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) | |
| endif() | |
| if (MPI_COMPILER_RETURN EQUAL 0 AND DEFINED MPI_COMPILE_CMDLINE) | |
| # Intel MPI can be run with -compchk or I_MPI_CHECK_COMPILER set to 1. | |
| # In this case, -show will be prepended with a line to the compiler checker. This is a script that performs | |
| # compatibility checks and returns a non-zero exit code together with an error if something fails. | |
| # It has to be called as "compchk.sh <arch> <compiler>". Here, <arch> is one out of 32 (i686), 64 (ia64) or 32e (x86_64). | |
| # The compiler is identified by filename, and can be either the MPI compiler or the underlying compiler. | |
| # NOTE: It is vital to run this script while the environment variables are set up, otherwise it can check the wrong compiler. | |
| if("${MPI_COMPILE_CMDLINE}" MATCHES "^([^\" ]+/compchk.sh|\"[^\"]+/compchk.sh\") +([^ ]+)") | |
| # Now CMAKE_MATCH_1 contains the path to the compchk.sh file and CMAKE_MATCH_2 the architecture flag. | |
| unset(COMPILER_CHECKER_OUTPUT) | |
| execute_process( | |
| COMMAND ${CMAKE_MATCH_1} ${CMAKE_MATCH_2} ${MPI_${LANG}_COMPILER} | |
| OUTPUT_VARIABLE COMPILER_CHECKER_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE | |
| ERROR_VARIABLE COMPILER_CHECKER_OUTPUT ERROR_STRIP_TRAILING_WHITESPACE | |
| RESULT_VARIABLE MPI_COMPILER_RETURN) | |
| # If it returned a non-zero value, the check below will fail and cause the interrogation to be aborted. | |
| if(NOT MPI_COMPILER_RETURN EQUAL 0) | |
| if(NOT MPI_FIND_QUIETLY) | |
| message(STATUS "Intel MPI compiler check failed: ${COMPILER_CHECKER_OUTPUT}") | |
| endif() | |
| else() | |
| # Since the check passed, we can remove the compchk.sh script. | |
| string(REGEX REPLACE "^([^\" ]+|\"[^\"]+\")/compchk.sh.*\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") | |
| endif() | |
| endif() | |
| endif() | |
| # Revert changes to the environment made previously | |
| if("${LANG}" STREQUAL "C") | |
| _MPI_env_unset_ifnot(I_MPI_CC) | |
| _MPI_env_unset_ifnot(MPICH_CC) | |
| elseif("${LANG}" STREQUAL "CXX") | |
| _MPI_env_unset_ifnot(I_MPI_CXX) | |
| _MPI_env_unset_ifnot(MPICH_CXX) | |
| elseif("${LANG}" STREQUAL "Fortran") | |
| _MPI_env_unset_ifnot(I_MPI_FC) | |
| _MPI_env_unset_ifnot(MPICH_FC) | |
| _MPI_env_unset_ifnot(I_MPI_F77) | |
| _MPI_env_unset_ifnot(MPICH_F77) | |
| _MPI_env_unset_ifnot(I_MPI_F90) | |
| _MPI_env_unset_ifnot(MPICH_F90) | |
| endif() | |
| _MPI_env_unset_ifnot(I_MPI_DEBUG_INFO_STRIP) | |
| _MPI_env_unset_ifnot(I_MPI_FORT_BIND) | |
| if (NOT (MPI_COMPILER_RETURN EQUAL 0) OR NOT (DEFINED MPI_COMPILE_CMDLINE)) | |
| # Cannot interrogate this compiler, so exit. | |
| set(MPI_${LANG}_WRAPPER_FOUND FALSE PARENT_SCOPE) | |
| return() | |
| endif() | |
| unset(MPI_COMPILER_RETURN) | |
| # We have our command lines, but we might need to copy MPI_COMPILE_CMDLINE | |
| # into MPI_LINK_CMDLINE, if we didn't find the link line. | |
| if (NOT DEFINED MPI_LINK_CMDLINE) | |
| set(MPI_LINK_CMDLINE "${MPI_COMPILE_CMDLINE}") | |
| endif() | |
| # Visual Studio parsers permit each flag prefixed by either / or -. | |
| # We'll normalize this to the - syntax we use for CMake purposes anyways. | |
| if(MSVC) | |
| foreach(_MPI_VARIABLE IN ITEMS COMPILE LINK) | |
| # The Intel MPI wrappers on Windows prefix their output with some copyright boilerplate. | |
| # To prevent possible problems, we discard this text before proceeding with any further matching. | |
| string(REGEX REPLACE "^[^ ]+ for the Intel\\(R\\) MPI Library [^\n]+ for Windows\\*\nCopyright\\(C\\) [^\n]+, Intel Corporation\\. All rights reserved\\.\n\n" "" | |
| MPI_${_MPI_VARIABLE}_CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}") | |
| string(REGEX REPLACE "(^| )/" "\\1-" MPI_${_MPI_VARIABLE}_CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}") | |
| string(REPLACE "-libpath:" "-LIBPATH:" MPI_${_MPI_VARIABLE}_CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}") | |
| endforeach() | |
| endif() | |
| # For MSVC and cl-compatible compilers, the keyword /link indicates a point after which | |
| # everything following is passed to the linker. In this case, we drop all prior information | |
| # from the link line and treat any unknown extra flags as linker flags. | |
| set(_MPI_FILTERED_LINK_INFORMATION FALSE) | |
| if(MSVC) | |
| if(MPI_LINK_CMDLINE MATCHES " -(link|LINK) ") | |
| string(REGEX REPLACE ".+-(link|LINK) +" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") | |
| set(_MPI_FILTERED_LINK_INFORMATION TRUE) | |
| endif() | |
| string(REGEX REPLACE " +-(link|LINK) .+" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") | |
| endif() | |
| if(UNIX) | |
| # At this point, we obtained some output from a compiler wrapper that works. | |
| # We'll now try to parse it into variables with meaning to us. | |
| if("${LANG}" STREQUAL "Fortran") | |
| # If MPICH (and derivates) didn't recognize the Fortran compiler include flag during configuration, | |
| # they'll return a set of three commands, consisting out of a symlink command for mpif.h, | |
| # the actual compiler command and deletion of the created symlink. | |
| # Especially with M(VA)PICH-1, this appears to happen erroneously, and therefore we should translate | |
| # this output into an additional include directory and then drop it from the output. | |
| if("${MPI_COMPILE_CMDLINE}" MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h") | |
| get_filename_component(MPI_INCLUDE_DIRS_WORK "${CMAKE_MATCH_1}" DIRECTORY) | |
| string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") | |
| string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") | |
| string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") | |
| string(REGEX REPLACE "\nrm -f mpif.h$" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") | |
| endif() | |
| endif() | |
| # If Intel MPI was configured for static linkage with -static_mpi, the wrapper will by default strip | |
| # debug information from resulting binaries (see I_MPI_DEBUG_INFO_STRIP). | |
| # Since we cannot process this information into CMake logic, we need to discard the resulting objcopy | |
| # commands from the output. | |
| string(REGEX REPLACE "(^|\n)objcopy[^\n]+(\n|$)" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") | |
| string(REGEX REPLACE "(^|\n)objcopy[^\n]+(\n|$)" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") | |
| endif() | |
| # For Visual C++, extracting compiler options in a generic fashion isn't easy. However, no MPI implementation | |
| # on Windows seems to require any specific ones, either. | |
| if(NOT MSVC) | |
| # Extract compile options from the compile command line. | |
| string(REGEX MATCHALL "(^| )-f([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_OPTIONS "${MPI_COMPILE_CMDLINE}") | |
| foreach(_MPI_COMPILE_OPTION IN LISTS MPI_ALL_COMPILE_OPTIONS) | |
| string(REGEX REPLACE "^ " "" _MPI_COMPILE_OPTION "${_MPI_COMPILE_OPTION}") | |
| # Ignore -fstack-protector directives: These occur on MPICH and MVAPICH when the libraries | |
| # themselves were built with this flag. However, this flag is unrelated to using MPI, and | |
| # we won't match the accompanying --param-ssp-size and -Wp,-D_FORTIFY_SOURCE flags and therefore | |
| # produce inconsistent results with the regularly flags. | |
| # Similarly, aliasing flags do not belong into our flag array. | |
| # Also strip out `-framework` flags. | |
| if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce]|ramework)") | |
| list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}") | |
| endif() | |
| endforeach() | |
| endif() | |
| # For GNU-style compilers, it's possible to prefix includes and definitions with certain flags to pass them | |
| # only to the preprocessor. For CMake purposes, we need to treat, but ignore such scopings. | |
| # Note that we do not support spaces between the arguments, i.e. -Wp,-I -Wp,/opt/mympi will not be parsed | |
| # correctly. This form does not seem to occur in any common MPI implementation, however. | |
| if(NOT MSVC) | |
| set(_MPI_PREPROCESSOR_FLAG_REGEX "(-Wp,|-Xpreprocessor )?") | |
| else() | |
| set(_MPI_PREPROCESSOR_FLAG_REGEX "") | |
| endif() | |
| # Same deal as above, for the definitions. | |
| string(REGEX MATCHALL "(^| )${_MPI_PREPROCESSOR_FLAG_REGEX}-D *([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_DEFINITIONS "${MPI_COMPILE_CMDLINE}") | |
| foreach(_MPI_COMPILE_DEFINITION IN LISTS MPI_ALL_COMPILE_DEFINITIONS) | |
| string(REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}-D *" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") | |
| string(REPLACE "\"" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") | |
| if(NOT "${_MPI_COMPILE_DEFINITION}" MATCHES "^_FORTIFY_SOURCE.*") | |
| list(APPEND MPI_COMPILE_DEFINITIONS_WORK "${_MPI_COMPILE_DEFINITION}") | |
| endif() | |
| endforeach() | |
| # Extract include paths from compile command line | |
| string(REGEX MATCHALL "(^| )${_MPI_PREPROCESSOR_FLAG_REGEX}${CMAKE_INCLUDE_FLAG_${LANG}} *([^\" ]+|\"[^\"]+\")" | |
| MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}") | |
| # If extracting failed to work, we'll try using -showme:incdirs. | |
| # Unlike before, we do this without the environment variables set up, but since only MPICH derivates are affected by any of them, and | |
| # -showme:... is only supported by Open MPI and LAM/MPI, this isn't a concern. | |
| if (NOT MPI_ALL_INCLUDE_PATHS) | |
| _MPI_check_compiler(${LANG} "-showme:incdirs" MPI_INCDIRS_CMDLINE MPI_INCDIRS_COMPILER_RETURN) | |
| if(MPI_INCDIRS_COMPILER_RETURN) | |
| separate_arguments(MPI_ALL_INCLUDE_PATHS NATIVE_COMMAND "${MPI_INCDIRS_CMDLINE}") | |
| endif() | |
| endif() | |
| foreach(_MPI_INCLUDE_PATH IN LISTS MPI_ALL_INCLUDE_PATHS) | |
| string(REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}${CMAKE_INCLUDE_FLAG_${LANG}} *" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}") | |
| string(REPLACE "\"" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}") | |
| string(REPLACE "'" "" _MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}") | |
| get_filename_component(_MPI_INCLUDE_PATH "${_MPI_INCLUDE_PATH}" REALPATH) | |
| list(APPEND MPI_INCLUDE_DIRS_WORK "${_MPI_INCLUDE_PATH}") | |
| endforeach() | |
| # The next step are linker flags and library directories. Here, we first take the flags given in raw -L or -LIBPATH: syntax. | |
| string(REGEX MATCHALL "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\" ]+|\"[^\"]+\")" MPI_DIRECT_LINK_PATHS "${MPI_LINK_CMDLINE}") | |
| foreach(_MPI_LPATH IN LISTS MPI_DIRECT_LINK_PATHS) | |
| string(REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *" "" _MPI_LPATH "${_MPI_LPATH}") | |
| list(APPEND MPI_ALL_LINK_PATHS "${_MPI_LPATH}") | |
| endforeach() | |
| # If the link commandline hasn't been filtered (e.g. when using MSVC and /link), we need to extract the relevant parts first. | |
| if(NOT _MPI_FILTERED_LINK_INFORMATION) | |
| string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\" ]+|\"[^\"]+\")" MPI_LINK_FLAGS "${MPI_LINK_CMDLINE}") | |
| # In this case, we could also find some indirectly given linker paths, e.g. prefixed by -Xlinker or -Wl, | |
| # Since syntaxes like -Wl,-L -Wl,/my/path/to/lib are also valid, we parse these paths by first removing -Wl, and -Xlinker | |
| # from the list of filtered flags and then parse the remainder of the output. | |
| string(REGEX REPLACE "(-Wl,|-Xlinker +)" "" MPI_LINK_FLAGS_RAW "${MPI_LINK_FLAGS}") | |
| # Now we can parse the leftover output. Note that spaces can now be handled since the above example would reduce to | |
| # -L /my/path/to/lib and can be extracted correctly. | |
| string(REGEX MATCHALL "^(${CMAKE_LIBRARY_PATH_FLAG},? *|--library-path=)([^\" ]+|\"[^\"]+\")" | |
| MPI_INDIRECT_LINK_PATHS "${MPI_LINK_FLAGS_RAW}") | |
| foreach(_MPI_LPATH IN LISTS MPI_INDIRECT_LINK_PATHS) | |
| string(REGEX REPLACE "^(${CMAKE_LIBRARY_PATH_FLAG},? *|--library-path=)" "" _MPI_LPATH "${_MPI_LPATH}") | |
| list(APPEND MPI_ALL_LINK_PATHS "${_MPI_LPATH}") | |
| endforeach() | |
| # We need to remove the flags we extracted from the linker flag list now. | |
| string(REGEX REPLACE "(^| )(-Wl,|-Xlinker +)(${CMAKE_LIBRARY_PATH_FLAG},? *(-Wl,|-Xlinker +)?|--library-path=)([^\" ]+|\"[^\"]+\")" "" | |
| MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE}") | |
| # Some MPI implementations pass on options they themselves were built with. Since -z,noexecstack is a common | |
| # hardening, we should strip it. In general, the -z options should be undesirable. | |
| string(REGEX REPLACE "(^| )-Wl,-z(,[^ ]+| +-Wl,[^ ]+)" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE_FILTERED}") | |
| string(REGEX REPLACE "(^| )-Xlinker +-z +-Xlinker +[^ ]+" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE_FILTERED}") | |
| # We only consider options of the form -Wl or -Xlinker: | |
| string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker +)([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE_FILTERED}") | |
| # As a next step, we assemble the linker flags extracted in a preliminary flags string | |
| foreach(_MPI_LINK_FLAG IN LISTS MPI_ALL_LINK_FLAGS) | |
| string(STRIP "${_MPI_LINK_FLAG}" _MPI_LINK_FLAG) | |
| if (MPI_LINK_FLAGS_WORK) | |
| string(APPEND MPI_LINK_FLAGS_WORK " ${_MPI_LINK_FLAG}") | |
| else() | |
| set(MPI_LINK_FLAGS_WORK "${_MPI_LINK_FLAG}") | |
| endif() | |
| endforeach() | |
| else() | |
| # In the filtered case, we obtain the link time flags by just stripping the library paths. | |
| string(REGEX REPLACE "(^| )${CMAKE_LIBRARY_PATH_FLAG} *([^\" ]+|\"[^\"]+\")" "" MPI_LINK_CMDLINE_FILTERED "${MPI_LINK_CMDLINE}") | |
| endif() | |
| # If we failed to extract any linker paths, we'll try using the -showme:libdirs option with the MPI compiler. | |
| # This will return a list of folders, not a set of flags! | |
| if (NOT MPI_ALL_LINK_PATHS) | |
| _MPI_check_compiler(${LANG} "-showme:libdirs" MPI_LIBDIRS_CMDLINE MPI_LIBDIRS_COMPILER_RETURN) | |
| if(MPI_LIBDIRS_COMPILER_RETURN) | |
| separate_arguments(MPI_ALL_LINK_PATHS NATIVE_COMMAND "${MPI_LIBDIRS_CMDLINE}") | |
| endif() | |
| endif() | |
| # We need to remove potential quotes and convert the paths to CMake syntax while resolving them, too. | |
| foreach(_MPI_LPATH IN LISTS MPI_ALL_LINK_PATHS) | |
| string(REPLACE "\"" "" _MPI_LPATH "${_MPI_LPATH}") | |
| get_filename_component(_MPI_LPATH "${_MPI_LPATH}" REALPATH) | |
| list(APPEND MPI_LINK_DIRECTORIES_WORK "${_MPI_LPATH}") | |
| endforeach() | |
| # Extract the set of libraries to link against from the link command line | |
| # This only makes sense if CMAKE_LINK_LIBRARY_FLAG is defined, i.e. a -lxxxx syntax is supported by the compiler. | |
| if(CMAKE_LINK_LIBRARY_FLAG) | |
| string(REGEX MATCHALL "(^| )${CMAKE_LINK_LIBRARY_FLAG}([^\" ]+|\"[^\"]+\")" | |
| MPI_LIBNAMES "${MPI_LINK_CMDLINE}") | |
| foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) | |
| string(REGEX REPLACE "^ ?${CMAKE_LINK_LIBRARY_FLAG}" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") | |
| string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") | |
| list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") | |
| endforeach() | |
| endif() | |
| # Treat linker objects given by full path, for example static libraries, import libraries | |
| # or shared libraries if there aren't any import libraries in use on the system. | |
| # Note that we do not consider CMAKE_<TYPE>_LIBRARY_PREFIX intentionally here: The linker will for a given file | |
| # decide how to link it based on file type, not based on a prefix like 'lib'. | |
| set(_MPI_LIB_SUFFIX_REGEX "${CMAKE_STATIC_LIBRARY_SUFFIX}") | |
| if(DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX) | |
| if(NOT ("${CMAKE_IMPORT_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}")) | |
| string(APPEND _MPI_SUFFIX_REGEX "|${CMAKE_IMPORT_LIBRARY_SUFFIX}") | |
| endif() | |
| else() | |
| string(APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_SHARED_LIBRARY_SUFFIX}") | |
| endif() | |
| set(_MPI_LIB_NAME_REGEX "(([^\" ]+(${_MPI_LIB_SUFFIX_REGEX}))|(\"[^\"]+(${_MPI_LIB_SUFFIX_REGEX})\"))( +|$)") | |
| string(REPLACE "." "\\." _MPI_LIB_NAME_REGEX "${_MPI_LIB_NAME_REGEX}") | |
| string(REGEX MATCHALL "${_MPI_LIB_NAME_REGEX}" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") | |
| foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES) | |
| string(REGEX REPLACE "^ +\"?|\"? +$" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") | |
| get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) | |
| if(NOT "${_MPI_LIB_PATH}" STREQUAL "") | |
| list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") | |
| else() | |
| list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") | |
| endif() | |
| endforeach() | |
| # Save the explicitly given link directories | |
| set(MPI_LINK_DIRECTORIES_LEFTOVER "${MPI_LINK_DIRECTORIES_WORK}") | |
| # An MPI compiler wrapper could have its MPI libraries in the implicitly | |
| # linked directories of the compiler itself. | |
| if(DEFINED CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES) | |
| list(APPEND MPI_LINK_DIRECTORIES_WORK "${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}") | |
| endif() | |
| # Determine full path names for all of the libraries that one needs | |
| # to link against in an MPI program | |
| unset(MPI_PLAIN_LIB_NAMES_WORK) | |
| foreach(_MPI_LIB_NAME IN LISTS MPI_LIB_NAMES_WORK) | |
| get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB_NAME}" NAME_WE) | |
| list(APPEND MPI_PLAIN_LIB_NAMES_WORK "${_MPI_PLAIN_LIB_NAME}") | |
| find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY | |
| NAMES "${_MPI_LIB_NAME}" "lib${_MPI_LIB_NAME}" | |
| HINTS ${MPI_LINK_DIRECTORIES_WORK} | |
| DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" | |
| ) | |
| mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) | |
| # Remove the directory from the remainder list. | |
| if(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) | |
| get_filename_component(_MPI_TAKEN_DIRECTORY "${MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY}" DIRECTORY) | |
| list(REMOVE_ITEM MPI_LINK_DIRECTORIES_LEFTOVER "${_MPI_TAKEN_DIRECTORY}") | |
| endif() | |
| endforeach() | |
| # Add the link directories given explicitly that we haven't used back as linker directories. | |
| if(NOT WIN32) | |
| foreach(_MPI_LINK_DIRECTORY IN LISTS MPI_LINK_DIRECTORIES_LEFTOVER) | |
| file(TO_NATIVE_PATH "${_MPI_LINK_DIRECTORY}" _MPI_LINK_DIRECTORY_ACTUAL) | |
| string(FIND "${_MPI_LINK_DIRECTORY_ACTUAL}" " " _MPI_LINK_DIRECTORY_CONTAINS_SPACE) | |
| if(NOT _MPI_LINK_DIRECTORY_CONTAINS_SPACE EQUAL -1) | |
| set(_MPI_LINK_DIRECTORY_ACTUAL "\"${_MPI_LINK_DIRECTORY_ACTUAL}\"") | |
| endif() | |
| if(MPI_LINK_FLAGS_WORK) | |
| string(APPEND MPI_LINK_FLAGS_WORK " ${CMAKE_LIBRARY_PATH_FLAG}${_MPI_LINK_DIRECTORY_ACTUAL}") | |
| else() | |
| set(MPI_LINK_FLAGS_WORK "${CMAKE_LIBRARY_PATH_FLAG}${_MPI_LINK_DIRECTORY_ACTUAL}") | |
| endif() | |
| endforeach() | |
| endif() | |
| # Deal with the libraries given with full path next | |
| unset(MPI_DIRECT_LIB_NAMES_WORK) | |
| foreach(_MPI_LIB_FULLPATH IN LISTS MPI_LIB_FULLPATHS_WORK) | |
| get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB_FULLPATH}" NAME_WE) | |
| list(APPEND MPI_DIRECT_LIB_NAMES_WORK "${_MPI_PLAIN_LIB_NAME}") | |
| set(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY "${_MPI_LIB_FULLPATH}" CACHE FILEPATH "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI") | |
| mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) | |
| endforeach() | |
| # Directly linked objects should be linked first in case some generic linker flags are needed for them. | |
| if(MPI_DIRECT_LIB_NAMES_WORK) | |
| set(MPI_PLAIN_LIB_NAMES_WORK "${MPI_DIRECT_LIB_NAMES_WORK};${MPI_PLAIN_LIB_NAMES_WORK}") | |
| endif() | |
| # MPI might require pthread to work. The above mechanism wouldn't detect it, but we need to | |
| # link it in that case. -lpthread is covered by the normal library treatment on the other hand. | |
| if("${MPI_COMPILE_CMDLINE}" MATCHES "-pthread") | |
| list(APPEND MPI_COMPILE_OPTIONS_WORK "-pthread") | |
| if(MPI_LINK_FLAGS_WORK) | |
| string(APPEND MPI_LINK_FLAGS_WORK " -pthread") | |
| else() | |
| set(MPI_LINK_FLAGS_WORK "-pthread") | |
| endif() | |
| endif() | |
| if(MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS) | |
| list(APPEND MPI_COMPILE_DEFINITIONS_WORK "${MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS}") | |
| endif() | |
| if(MPI_${LANG}_EXTRA_COMPILE_OPTIONS) | |
| list(APPEND MPI_COMPILE_OPTIONS_WORK "${MPI_${LANG}_EXTRA_COMPILE_OPTIONS}") | |
| endif() | |
| if(MPI_${LANG}_EXTRA_LIB_NAMES) | |
| list(APPEND MPI_PLAIN_LIB_NAMES_WORK "${MPI_${LANG}_EXTRA_LIB_NAMES}") | |
| endif() | |
| # If we found MPI, set up all of the appropriate cache entries | |
| if(NOT MPI_${LANG}_COMPILE_OPTIONS) | |
| set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_COMPILE_OPTIONS_WORK} CACHE STRING "MPI ${LANG} compilation options" FORCE) | |
| endif() | |
| if(NOT MPI_${LANG}_COMPILE_DEFINITIONS) | |
| set(MPI_${LANG}_COMPILE_DEFINITIONS ${MPI_COMPILE_DEFINITIONS_WORK} CACHE STRING "MPI ${LANG} compilation definitions" FORCE) | |
| endif() | |
| if(NOT MPI_${LANG}_COMPILER_INCLUDE_DIRS) | |
| set(MPI_${LANG}_COMPILER_INCLUDE_DIRS ${MPI_INCLUDE_DIRS_WORK} CACHE STRING "MPI ${LANG} compiler wrapper include directories" FORCE) | |
| endif() | |
| if(NOT MPI_${LANG}_LINK_FLAGS) | |
| set(MPI_${LANG}_LINK_FLAGS ${MPI_LINK_FLAGS_WORK} CACHE STRING "MPI ${LANG} linker flags" FORCE) | |
| endif() | |
| if(NOT MPI_${LANG}_LIB_NAMES) | |
| set(MPI_${LANG}_LIB_NAMES ${MPI_PLAIN_LIB_NAMES_WORK} CACHE STRING "MPI ${LANG} libraries to link against" FORCE) | |
| endif() | |
| set(MPI_${LANG}_WRAPPER_FOUND TRUE PARENT_SCOPE) | |
| endfunction() | |
| function(_MPI_guess_settings LANG) | |
| set(MPI_GUESS_FOUND FALSE) | |
| # Currently only MSMPI and MPICH2 on Windows are supported, so we can skip this search if we're not targeting that. | |
| if(WIN32) | |
| # MSMPI | |
| # The environment variables MSMPI_INC and MSMPILIB32/64 are the only ways of locating the MSMPI_SDK, | |
| # which is installed separately from the runtime. Thus it's possible to have mpiexec but not MPI headers | |
| # or import libraries and vice versa. | |
| if(NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MSMPI") | |
| # We first attempt to locate the msmpi.lib. Should be find it, we'll assume that the MPI present is indeed | |
| # Microsoft MPI. | |
| if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) | |
| file(TO_CMAKE_PATH "$ENV{MSMPI_LIB64}" MPI_MSMPI_LIB_PATH) | |
| file(TO_CMAKE_PATH "$ENV{MSMPI_INC}/x64" MPI_MSMPI_INC_PATH_EXTRA) | |
| else() | |
| file(TO_CMAKE_PATH "$ENV{MSMPI_LIB32}" MPI_MSMPI_LIB_PATH) | |
| file(TO_CMAKE_PATH "$ENV{MSMPI_INC}/x86" MPI_MSMPI_INC_PATH_EXTRA) | |
| endif() | |
| find_library(MPI_msmpi_LIBRARY | |
| NAMES msmpi | |
| HINTS ${MPI_MSMPI_LIB_PATH} | |
| DOC "Location of the msmpi library for Microsoft MPI") | |
| mark_as_advanced(MPI_msmpi_LIBRARY) | |
| if(MPI_msmpi_LIBRARY) | |
| # Next, we attempt to locate the MPI header. Note that for Fortran we know that mpif.h is a way | |
| # MSMPI can be used and therefore that header has to be present. | |
| if(NOT MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) | |
| get_filename_component(MPI_MSMPI_INC_DIR "$ENV{MSMPI_INC}" REALPATH) | |
| set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_MSMPI_INC_DIR}" CACHE STRING "MPI ${LANG} additional include directories" FORCE) | |
| unset(MPI_MSMPI_INC_DIR) | |
| endif() | |
| # For MSMPI, one can compile the MPI module by building the mpi.f90 shipped with the MSMPI SDK, | |
| # thus it might be present or provided by the user. Figuring out which is supported is done later on. | |
| # The PGI Fortran compiler for instance ships a prebuilt set of modules in its own include folder. | |
| # Should a user be employing PGI or have built its own set and provided it via cache variables, the | |
| # splitting routine would have located the module files. | |
| # For C and C++, we're done here (MSMPI does not ship the MPI-2 C++ bindings) - however, for Fortran | |
| # we need some extra library to glue Fortran support together: | |
| # MSMPI ships 2-4 Fortran libraries, each for different Fortran compiler behaviors. The library names | |
| # ending with a c are using the cdecl calling convention, whereas those ending with an s are for Fortran | |
| # implementations using stdcall. Therefore, the 64-bit MSMPI only ships those ending in 'c', whereas the 32-bit | |
| # has both variants available. | |
| # The second difference is the last but one letter, if it's an e(nd), the length of a string argument is | |
| # passed by the Fortran compiler after all other arguments on the parameter list, if it's an m(ixed), | |
| # it's passed immediately after the string address. | |
| # To summarize: | |
| # - msmpifec: CHARACTER length passed after the parameter list and using cdecl calling convention | |
| # - msmpifmc: CHARACTER length passed directly after string address and using cdecl calling convention | |
| # - msmpifes: CHARACTER length passed after the parameter list and using stdcall calling convention | |
| # - msmpifms: CHARACTER length passed directly after string address and using stdcall calling convention | |
| # 32-bit MSMPI ships all four libraries, 64-bit MSMPI ships only the first two. | |
| # As is, Intel Fortran and PGI Fortran both use the 'ec' variant of the calling convention, whereas | |
| # the old Compaq Visual Fortran compiler defaulted to the 'ms' version. It's possible to make Intel Fortran | |
| # use the CVF calling convention using /iface:cvf, but we assume - and this is also assumed in FortranCInterface - | |
| # this isn't the case. It's also possible to make CVF use the 'ec' variant, using /iface=(cref,nomixed_str_len_arg). | |
| # Our strategy is now to locate all libraries, but enter msmpifec into the LIB_NAMES array. | |
| # Should this not be adequate it's a straightforward way for a user to change the LIB_NAMES array and | |
| # have his library found. Still, this should not be necessary outside of exceptional cases, as reasoned. | |
| if ("${LANG}" STREQUAL "Fortran") | |
| set(MPI_MSMPI_CALLINGCONVS c) | |
| if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4) | |
| list(APPEND MPI_MSMPI_CALLINGCONVS s) | |
| endif() | |
| foreach(mpistrlenpos IN ITEMS e m) | |
| foreach(mpicallingconv IN LISTS MPI_MSMPI_CALLINGCONVS) | |
| find_library(MPI_msmpif${mpistrlenpos}${mpicallingconv}_LIBRARY | |
| NAMES msmpif${mpistrlenpos}${mpicallingconv} | |
| HINTS "${MPI_MSMPI_LIB_PATH}" | |
| DOC "Location of the msmpi${mpistrlenpos}${mpicallingconv} library for Microsoft MPI") | |
| mark_as_advanced(MPI_msmpif${mpistrlenpos}${mpicallingconv}_LIBRARY) | |
| endforeach() | |
| endforeach() | |
| if(NOT MPI_${LANG}_LIB_NAMES) | |
| set(MPI_${LANG}_LIB_NAMES "msmpi;msmpifec" CACHE STRING "MPI ${LANG} libraries to link against" FORCE) | |
| endif() | |
| # At this point we're *not* done. MSMPI requires an additional include file for Fortran giving the value | |
| # of MPI_AINT. This file is called mpifptr.h located in the x64 and x86 subfolders, respectively. | |
| find_path(MPI_mpifptr_INCLUDE_DIR | |
| NAMES "mpifptr.h" | |
| HINTS "${MPI_MSMPI_INC_PATH_EXTRA}" | |
| DOC "Location of the mpifptr.h extra header for Microsoft MPI") | |
| if(NOT MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) | |
| set(MPI_${LANG}_ADDITIONAL_INCLUDE_VARS "mpifptr" CACHE STRING "MPI ${LANG} additional include directory variables, given in the form MPI_<name>_INCLUDE_DIR." FORCE) | |
| endif() | |
| mark_as_advanced(MPI_${LANG}_ADDITIONAL_INCLUDE_VARS MPI_mpifptr_INCLUDE_DIR) | |
| else() | |
| if(NOT MPI_${LANG}_LIB_NAMES) | |
| set(MPI_${LANG}_LIB_NAMES "msmpi" CACHE STRING "MPI ${LANG} libraries to link against" FORCE) | |
| endif() | |
| endif() | |
| mark_as_advanced(MPI_${LANG}_LIB_NAMES) | |
| set(MPI_GUESS_FOUND TRUE) | |
| if(_MPIEXEC_NOT_GIVEN) | |
| unset(MPIEXEC_EXECUTABLE CACHE) | |
| endif() | |
| find_program(MPIEXEC_EXECUTABLE | |
| NAMES mpiexec | |
| HINTS $ENV{MSMPI_BIN} "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MPI;InstallRoot]/Bin" | |
| DOC "Executable for running MPI programs.") | |
| endif() | |
| endif() | |
| # At this point there's not many MPIs that we could still consider. | |
| # OpenMPI 1.6.x and below supported Windows, but these ship compiler wrappers that still work. | |
| # The only other relevant MPI implementation without a wrapper is MPICH2, which had Windows support in 1.4.1p1 and older. | |
| if(NOT MPI_GUESS_FOUND AND (NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MPICH2")) | |
| set(MPI_MPICH_PREFIX_PATHS | |
| "$ENV{ProgramW6432}/MPICH2/lib" | |
| "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH\\SMPD;binary]/../lib" | |
| "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH2;Path]/lib" | |
| ) | |
| # All of C, C++ and Fortran will need mpi.lib, so we'll look for this first | |
| find_library(MPI_mpi_LIBRARY | |
| NAMES mpi | |
| HINTS ${MPI_MPICH_PREFIX_PATHS}) | |
| mark_as_advanced(MPI_mpi_LIBRARY) | |
| # If we found mpi.lib, we detect the rest of MPICH2 | |
| if(MPI_mpi_LIBRARY) | |
| set(MPI_MPICH_LIB_NAMES "mpi") | |
| # If MPI-2 C++ bindings are requested, we need to locate cxx.lib as well. | |
| # Otherwise, MPICH_SKIP_MPICXX will be defined and these bindings aren't needed. | |
| if("${LANG}" STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX) | |
| find_library(MPI_cxx_LIBRARY | |
| NAMES cxx | |
| HINTS ${MPI_MPICH_PREFIX_PATHS}) | |
| mark_as_advanced(MPI_cxx_LIBRARY) | |
| list(APPEND MPI_MPICH_LIB_NAMES "cxx") | |
| # For Fortran, MPICH2 provides three different libraries: | |
| # fmpich2.lib which uses uppercase symbols and cdecl, | |
| # fmpich2s.lib which uses uppercase symbols and stdcall (32-bit only), | |
| # fmpich2g.lib which uses lowercase symbols with double underscores and cdecl. | |
| # fmpich2s.lib would be useful for Compaq Visual Fortran, fmpich2g.lib has to be used with GNU g77 and is also | |
| # provided in the form of an .a archive for MinGW and Cygwin. From our perspective, fmpich2.lib is the only one | |
| # we need to try, and if it doesn't work with the given Fortran compiler we'd find out later on during validation | |
| elseif("${LANG}" STREQUAL "Fortran") | |
| find_library(MPI_fmpich2_LIBRARY | |
| NAMES fmpich2 | |
| HINTS ${MPI_MPICH_PREFIX_PATHS}) | |
| find_library(MPI_fmpich2s_LIBRARY | |
| NAMES fmpich2s | |
| HINTS ${MPI_MPICH_PREFIX_PATHS}) | |
| find_library(MPI_fmpich2g_LIBRARY | |
| NAMES fmpich2g | |
| HINTS ${MPI_MPICH_PREFIX_PATHS}) | |
| mark_as_advanced(MPI_fmpich2_LIBRARY MPI_fmpich2s_LIBRARY MPI_fmpich2g_LIBRARY) | |
| list(APPEND MPI_MPICH_LIB_NAMES "fmpich2") | |
| endif() | |
| if(NOT MPI_${LANG}_LIB_NAMES) | |
| set(MPI_${LANG}_LIB_NAMES "${MPI_MPICH_LIB_NAMES}" CACHE STRING "MPI ${LANG} libraries to link against" FORCE) | |
| endif() | |
| unset(MPI_MPICH_LIB_NAMES) | |
| if(NOT MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) | |
| # For MPICH2, the include folder would be in ../include relative to the library folder. | |
| get_filename_component(MPI_MPICH_ROOT_DIR "${MPI_mpi_LIBRARY}" DIRECTORY) | |
| get_filename_component(MPI_MPICH_ROOT_DIR "${MPI_MPICH_ROOT_DIR}" DIRECTORY) | |
| if(IS_DIRECTORY "${MPI_MPICH_ROOT_DIR}/include") | |
| set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_MPICH_ROOT_DIR}/include" CACHE STRING "MPI ${LANG} additional include directory variables, given in the form MPI_<name>_INCLUDE_DIR." FORCE) | |
| endif() | |
| unset(MPI_MPICH_ROOT_DIR) | |
| endif() | |
| set(MPI_GUESS_FOUND TRUE) | |
| if(_MPIEXEC_NOT_GIVEN) | |
| unset(MPIEXEC_EXECUTABLE CACHE) | |
| endif() | |
| find_program(MPIEXEC_EXECUTABLE | |
| NAMES ${_MPIEXEC_NAMES} | |
| HINTS "$ENV{ProgramW6432}/MPICH2/bin" | |
| "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH\\SMPD;binary]" | |
| "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH2;Path]/bin" | |
| DOC "Executable for running MPI programs.") | |
| endif() | |
| unset(MPI_MPICH_PREFIX_PATHS) | |
| endif() | |
| endif() | |
| set(MPI_${LANG}_GUESS_FOUND "${MPI_GUESS_FOUND}" PARENT_SCOPE) | |
| endfunction() | |
| function(_MPI_adjust_compile_definitions LANG) | |
| if("${LANG}" STREQUAL "CXX") | |
| # To disable the C++ bindings, we need to pass some definitions since the mpi.h header has to deal with both C and C++ | |
| # bindings in MPI-2. | |
| if(MPI_CXX_SKIP_MPICXX AND NOT MPI_${LANG}_COMPILE_DEFINITIONS MATCHES "SKIP_MPICXX") | |
| # MPICH_SKIP_MPICXX is being used in MPICH and derivatives like MVAPICH or Intel MPI | |
| # OMPI_SKIP_MPICXX is being used in Open MPI | |
| # _MPICC_H is being used for IBM Platform MPI | |
| list(APPEND MPI_${LANG}_COMPILE_DEFINITIONS "MPICH_SKIP_MPICXX" "OMPI_SKIP_MPICXX" "_MPICC_H") | |
| set(MPI_${LANG}_COMPILE_DEFINITIONS "${MPI_${LANG}_COMPILE_DEFINITIONS}" CACHE STRING "MPI ${LANG} compilation definitions" FORCE) | |
| endif() | |
| endif() | |
| endfunction() | |
| macro(_MPI_assemble_libraries LANG) | |
| set(MPI_${LANG}_LIBRARIES "") | |
| # Only for libraries do we need to check whether the compiler's linking stage is separate. | |
| if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_${LANG}_WORKS_IMPLICIT) | |
| foreach(mpilib IN LISTS MPI_${LANG}_LIB_NAMES) | |
| list(APPEND MPI_${LANG}_LIBRARIES ${MPI_${mpilib}_LIBRARY}) | |
| endforeach() | |
| endif() | |
| endmacro() | |
| macro(_MPI_assemble_include_dirs LANG) | |
| set(MPI_${LANG}_INCLUDE_DIRS | |
| ${MPI_${LANG}_COMPILER_INCLUDE_DIRS} | |
| ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} | |
| ) | |
| if("${LANG}" MATCHES "(C|CXX)") | |
| if(MPI_${LANG}_HEADER_DIR) | |
| list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}") | |
| endif() | |
| else() # Fortran | |
| if(MPI_${LANG}_F77_HEADER_DIR) | |
| list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_F77_HEADER_DIR}") | |
| endif() | |
| if(MPI_${LANG}_MODULE_DIR) | |
| list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_MODULE_DIR}") | |
| endif() | |
| endif() | |
| if(MPI_${LANG}_INCLUDE_DIRS) | |
| list(REMOVE_DUPLICATES MPI_${LANG}_INCLUDE_DIRS) | |
| endif() | |
| endmacro() | |
| macro(_MPI_split_include_dirs LANG) | |
| # Backwards compatibility: Search INCLUDE_PATH if given. | |
| if(MPI_${LANG}_INCLUDE_PATH) | |
| list(APPEND MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_${LANG}_INCLUDE_PATH}") | |
| endif() | |
| # We try to find the headers/modules among those paths (and system paths) | |
| # For C/C++, we just need to have a look for mpi.h. | |
| if("${LANG}" MATCHES "(C|CXX)") | |
| find_path(MPI_${LANG}_HEADER_DIR "mpi.h" | |
| HINTS | |
| ${MPI_${LANG}_COMPILER_INCLUDE_DIRS} | |
| ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} | |
| ) | |
| mark_as_advanced(MPI_${LANG}_HEADER_DIR) | |
| if(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) | |
| list(REMOVE_ITEM MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}") | |
| endif() | |
| # Fortran is more complicated here: An implementation could provide | |
| # any of the Fortran 77/90/2008 APIs for MPI. For example, MSMPI | |
| # only provides Fortran 77 and - if mpi.f90 is built - potentially | |
| # a Fortran 90 module. | |
| elseif("${LANG}" STREQUAL "Fortran") | |
| find_path(MPI_${LANG}_F77_HEADER_DIR "mpif.h" | |
| HINTS | |
| ${MPI_${LANG}_COMPILER_INCLUDE_DIRS} | |
| ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} | |
| ) | |
| find_path(MPI_${LANG}_MODULE_DIR | |
| NAMES "mpi.mod" "mpi_f08.mod" | |
| HINTS | |
| ${MPI_${LANG}_COMPILER_INCLUDE_DIRS} | |
| ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} | |
| ) | |
| if(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) | |
| list(REMOVE_ITEM MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS | |
| "${MPI_${LANG}_F77_HEADER_DIR}" | |
| "${MPI_${LANG}_MODULE_DIR}" | |
| ) | |
| endif() | |
| mark_as_advanced(MPI_${LANG}_F77_HEADER_DIR MPI_${LANG}_MODULE_DIR) | |
| endif() | |
| # Remove duplicates and default system directories from the list. | |
| if(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) | |
| list(REMOVE_DUPLICATES MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS) | |
| foreach(MPI_IMPLICIT_INC_DIR IN LISTS CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES) | |
| list(REMOVE_ITEM MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS ${MPI_IMPLICIT_INC_DIR}) | |
| endforeach() | |
| endif() | |
| set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} additional include directories" FORCE) | |
| endmacro() | |
| macro(_MPI_create_imported_target LANG) | |
| if(NOT TARGET MPI::MPI_${LANG}) | |
| add_library(MPI::MPI_${LANG} INTERFACE IMPORTED) | |
| endif() | |
| # When this is consumed for compiling CUDA, use '-Xcompiler' to wrap '-pthread' and '-fexceptions'. | |
| string(REPLACE "-pthread" "$<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:SHELL:-Xcompiler >-pthread" | |
| _MPI_${LANG}_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}") | |
| string(REPLACE "-fexceptions" "$<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:SHELL:-Xcompiler >-fexceptions" | |
| _MPI_${LANG}_COMPILE_OPTIONS "${_MPI_${LANG}_COMPILE_OPTIONS}") | |
| set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_OPTIONS "${_MPI_${LANG}_COMPILE_OPTIONS}") | |
| unset(_MPI_${LANG}_COMPILE_OPTIONS) | |
| set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_DEFINITIONS "${MPI_${LANG}_COMPILE_DEFINITIONS}") | |
| if(MPI_${LANG}_LINK_FLAGS) | |
| string(REPLACE "," "$<COMMA>" _MPI_${LANG}_LINK_FLAGS "${MPI_${LANG}_LINK_FLAGS}") | |
| string(PREPEND _MPI_${LANG}_LINK_FLAGS "$<HOST_LINK:SHELL:") | |
| string(APPEND _MPI_${LANG}_LINK_FLAGS ">") | |
| set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_LINK_OPTIONS "${_MPI_${LANG}_LINK_FLAGS}") | |
| endif() | |
| # If the compiler links MPI implicitly, no libraries will be found as they're contained within | |
| # CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES already. | |
| if(MPI_${LANG}_LIBRARIES) | |
| set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_LINK_LIBRARIES "${MPI_${LANG}_LIBRARIES}") | |
| endif() | |
| # Given the new design of FindMPI, INCLUDE_DIRS will always be located, even under implicit linking. | |
| set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MPI_${LANG}_INCLUDE_DIRS}") | |
| endmacro() | |
| function(_MPI_try_staged_settings LANG MPI_TEST_FILE_NAME MODE RUN_BINARY SUPPRESS_ERRORS) | |
| set(WORK_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI") | |
| set(SRC_DIR "${CMAKE_ROOT}/Modules/FindMPI") | |
| set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI/${MPI_TEST_FILE_NAME}_${LANG}.bin") | |
| unset(MPI_TEST_COMPILE_DEFINITIONS) | |
| if("${LANG}" STREQUAL "Fortran") | |
| if("${MODE}" STREQUAL "F90_MODULE") | |
| set(MPI_Fortran_INCLUDE_LINE "use mpi\n implicit none") | |
| elseif("${MODE}" STREQUAL "F08_MODULE") | |
| set(MPI_Fortran_INCLUDE_LINE "use mpi_f08\n implicit none") | |
| else() # F77 header | |
| set(MPI_Fortran_INCLUDE_LINE "implicit none\n include 'mpif.h'") | |
| endif() | |
| configure_file("${SRC_DIR}/${MPI_TEST_FILE_NAME}.f90.in" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90" @ONLY) | |
| set(MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90") | |
| elseif("${LANG}" STREQUAL "CXX") | |
| configure_file("${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp" COPYONLY) | |
| set(MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp") | |
| if("${MODE}" STREQUAL "TEST_MPICXX") | |
| set(MPI_TEST_COMPILE_DEFINITIONS TEST_MPI_MPICXX) | |
| endif() | |
| else() # C | |
| set(MPI_TEST_SOURCE_FILE "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c") | |
| endif() | |
| if(RUN_BINARY) | |
| try_run(MPI_RUN_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} | |
| "${CMAKE_BINARY_DIR}" SOURCES "${MPI_TEST_SOURCE_FILE}" | |
| COMPILE_DEFINITIONS ${MPI_TEST_COMPILE_DEFINITIONS} | |
| LINK_LIBRARIES MPI::MPI_${LANG} | |
| RUN_OUTPUT_VARIABLE MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} | |
| COMPILE_OUTPUT_VARIABLE _MPI_TRY_${MPI_TEST_FILE_NAME}_${MODE}_OUTPUT) | |
| set(MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} "${MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}}" PARENT_SCOPE) | |
| else() | |
| try_compile(MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} | |
| "${CMAKE_BINARY_DIR}" SOURCES "${MPI_TEST_SOURCE_FILE}" | |
| COMPILE_DEFINITIONS ${MPI_TEST_COMPILE_DEFINITIONS} | |
| LINK_LIBRARIES MPI::MPI_${LANG} | |
| COPY_FILE "${BIN_FILE}" | |
| OUTPUT_VARIABLE _MPI_TRY_${MPI_TEST_FILE_NAME}_${MODE}_OUTPUT) | |
| endif() | |
| if(NOT SUPPRESS_ERRORS) | |
| if(NOT MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}) | |
| file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log | |
| "The MPI test ${MPI_TEST_FILE_NAME} for ${LANG} in mode ${MODE} failed to compile with the following output:\n${_MPI_TRY_${MPI_TEST_FILE_NAME}_${MODE}_OUTPUT}\n\n") | |
| elseif(DEFINED MPI_RUN_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} AND MPI_RUN_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}) | |
| file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log | |
| "The MPI test ${MPI_TEST_FILE_NAME} for ${LANG} in mode ${MODE} failed to run with the following output:\n${MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}}\n\n") | |
| endif() | |
| endif() | |
| endfunction() | |
| macro(_MPI_check_lang_works LANG SUPPRESS_ERRORS) | |
| # For Fortran we may have by the MPI-3 standard an implementation that provides: | |
| # - the mpi_f08 module | |
| # - *both*, the mpi module and 'mpif.h' | |
| # Since older MPI standards (MPI-1) did not define anything but 'mpif.h', we need to check all three individually. | |
| if( NOT MPI_${LANG}_WORKS ) | |
| if("${LANG}" STREQUAL "Fortran") | |
| set(MPI_Fortran_INTEGER_LINE "(kind=MPI_INTEGER_KIND)") | |
| _MPI_try_staged_settings(${LANG} test_mpi F77_HEADER FALSE ${SUPPRESS_ERRORS}) | |
| _MPI_try_staged_settings(${LANG} test_mpi F90_MODULE FALSE ${SUPPRESS_ERRORS}) | |
| _MPI_try_staged_settings(${LANG} test_mpi F08_MODULE FALSE ${SUPPRESS_ERRORS}) | |
| set(MPI_${LANG}_WORKS FALSE) | |
| foreach(mpimethod IN ITEMS F77_HEADER F08_MODULE F90_MODULE) | |
| if(MPI_RESULT_${LANG}_test_mpi_${mpimethod}) | |
| set(MPI_${LANG}_WORKS TRUE) | |
| set(MPI_${LANG}_HAVE_${mpimethod} TRUE) | |
| else() | |
| set(MPI_${LANG}_HAVE_${mpimethod} FALSE) | |
| endif() | |
| endforeach() | |
| # MPI-1 versions had no MPI_INTGER_KIND defined, so we need to try without it. | |
| # However, MPI-1 also did not define the Fortran 90 and 08 modules, so we only try the F77 header. | |
| unset(MPI_Fortran_INTEGER_LINE) | |
| if(NOT MPI_${LANG}_WORKS) | |
| _MPI_try_staged_settings(${LANG} test_mpi F77_HEADER_NOKIND FALSE ${SUPPRESS_ERRORS}) | |
| if(MPI_RESULT_${LANG}_test_mpi_F77_HEADER_NOKIND) | |
| set(MPI_${LANG}_WORKS TRUE) | |
| set(MPI_${LANG}_HAVE_F77_HEADER TRUE) | |
| endif() | |
| endif() | |
| else() | |
| _MPI_try_staged_settings(${LANG} test_mpi normal FALSE ${SUPPRESS_ERRORS}) | |
| # If 'test_mpi' built correctly, we've found valid MPI settings. There might not be MPI-2 C++ support, but there can't | |
| # be MPI-2 C++ support without the C bindings being present, so checking for them is sufficient. | |
| set(MPI_${LANG}_WORKS "${MPI_RESULT_${LANG}_test_mpi_normal}") | |
| endif() | |
| endif() | |
| endmacro() | |
| # Some systems install various MPI implementations in separate folders in some MPI prefix | |
| # This macro enumerates all such subfolders and adds them to the list of hints that will be searched. | |
| macro(MPI_search_mpi_prefix_folder PREFIX_FOLDER) | |
| if(EXISTS "${PREFIX_FOLDER}") | |
| file(GLOB _MPI_folder_children RELATIVE "${PREFIX_FOLDER}" "${PREFIX_FOLDER}/*") | |
| foreach(_MPI_folder_child IN LISTS _MPI_folder_children) | |
| if(IS_DIRECTORY "${PREFIX_FOLDER}/${_MPI_folder_child}") | |
| list(APPEND MPI_HINT_DIRS "${PREFIX_FOLDER}/${_MPI_folder_child}") | |
| endif() | |
| endforeach() | |
| endif() | |
| endmacro() | |
| set(MPI_HINT_DIRS ${MPI_HOME} $ENV{MPI_HOME} $ENV{I_MPI_ROOT}) | |
| if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux") | |
| # SUSE Linux Enterprise Server stores its MPI implementations under /usr/lib64/mpi/gcc/<name> | |
| # We enumerate the subfolders and append each as a prefix | |
| MPI_search_mpi_prefix_folder("/usr/lib64/mpi/gcc") | |
| elseif("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "FreeBSD") | |
| # FreeBSD ships mpich under the normal system paths - but available openmpi implementations | |
| # will be found in /usr/local/mpi/<name> | |
| MPI_search_mpi_prefix_folder("/usr/local/mpi") | |
| endif() | |
| # Most MPI distributions have some form of mpiexec or mpirun which gives us something we can look for. | |
| # The MPI standard does not mandate the existence of either, but instead only makes requirements if a distribution | |
| # ships an mpiexec program (mpirun executables are not regulated by the standard). | |
| # We defer searching for mpiexec binaries belonging to guesses until later. By doing so, mismatches between mpiexec | |
| # and the MPI we found should be reduced. | |
| if(NOT MPIEXEC_EXECUTABLE) | |
| set(_MPIEXEC_NOT_GIVEN TRUE) | |
| else() | |
| set(_MPIEXEC_NOT_GIVEN FALSE) | |
| endif() | |
| find_program(MPIEXEC_EXECUTABLE | |
| NAMES ${_MPIEXEC_NAMES} | |
| PATH_SUFFIXES bin sbin | |
| HINTS ${MPI_HINT_DIRS} | |
| 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_EXECUTABLE}" PATH) | |
| get_filename_component(_MPI_BASE_DIR "${_MPI_BASE_DIR}" PATH) | |
| # According to the MPI standard, section 8.8 -n is a guaranteed, and the only guaranteed way to | |
| # launch an MPI process using mpiexec if such a program exists. | |
| set(MPIEXEC_NUMPROC_FLAG "-n" 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 be placed after all flags passed to mpiexec.") | |
| # Set the number of processes to the physical processor count | |
| cmake_host_system_information(RESULT _MPIEXEC_NUMPROCS QUERY NUMBER_OF_PHYSICAL_CORES) | |
| set(MPIEXEC_MAX_NUMPROCS "${_MPIEXEC_NUMPROCS}" CACHE STRING "Maximum number of processors available to run MPI applications.") | |
| unset(_MPIEXEC_NUMPROCS) | |
| mark_as_advanced(MPIEXEC_EXECUTABLE MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS) | |
| #============================================================================= | |
| # Backward compatibility input hacks. Propagate the FindMPI hints to C and | |
| # CXX if the respective new versions are not defined. Translate the old | |
| # MPI_LIBRARY and MPI_EXTRA_LIBRARY to respective MPI_${LANG}_LIBRARIES. | |
| # | |
| # Once we find the new variables, we translate them back into their old | |
| # equivalents below. | |
| if(NOT MPI_IGNORE_LEGACY_VARIABLES) | |
| foreach (LANG IN ITEMS C CXX) | |
| # Old input variables. | |
| set(_MPI_OLD_INPUT_VARS COMPILER COMPILE_FLAGS INCLUDE_PATH LINK_FLAGS) | |
| # Set new vars based on their old equivalents, if the new versions are not already set. | |
| foreach (var ${_MPI_OLD_INPUT_VARS}) | |
| if (NOT MPI_${LANG}_${var} AND MPI_${var}) | |
| set(MPI_${LANG}_${var} "${MPI_${var}}") | |
| endif() | |
| endforeach() | |
| # Chop the old compile flags into options and definitions | |
| unset(MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS) | |
| unset(MPI_${LANG}_EXTRA_COMPILE_OPTIONS) | |
| if(MPI_${LANG}_COMPILE_FLAGS) | |
| separate_arguments(MPI_SEPARATE_FLAGS NATIVE_COMMAND "${MPI_${LANG}_COMPILE_FLAGS}") | |
| foreach(_MPI_FLAG IN LISTS MPI_SEPARATE_FLAGS) | |
| if("${_MPI_FLAG}" MATCHES "^ *-D([^ ]+)") | |
| list(APPEND MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS "${CMAKE_MATCH_1}") | |
| else() | |
| list(APPEND MPI_${LANG}_EXTRA_COMPILE_OPTIONS "${_MPI_FLAG}") | |
| endif() | |
| endforeach() | |
| unset(MPI_SEPARATE_FLAGS) | |
| endif() | |
| # If a list of libraries was given, we'll split it into new-style cache variables | |
| unset(MPI_${LANG}_EXTRA_LIB_NAMES) | |
| if(NOT MPI_${LANG}_LIB_NAMES) | |
| foreach(_MPI_LIB IN LISTS MPI_${LANG}_LIBRARIES MPI_LIBRARY MPI_EXTRA_LIBRARY) | |
| if(_MPI_LIB) | |
| get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB}" NAME_WE) | |
| get_filename_component(_MPI_LIB_NAME "${_MPI_LIB}" NAME) | |
| get_filename_component(_MPI_LIB_DIR "${_MPI_LIB}" DIRECTORY) | |
| list(APPEND MPI_${LANG}_EXTRA_LIB_NAMES "${_MPI_PLAIN_LIB_NAME}") | |
| find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY | |
| NAMES "${_MPI_LIB_NAME}" "lib${_MPI_LIB_NAME}" | |
| HINTS ${_MPI_LIB_DIR} $ENV{MPI_LIB} | |
| DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" | |
| ) | |
| mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) | |
| endif() | |
| endforeach() | |
| endif() | |
| endforeach() | |
| endif() | |
| #============================================================================= | |
| unset(MPI_VERSION) | |
| unset(MPI_VERSION_MAJOR) | |
| unset(MPI_VERSION_MINOR) | |
| unset(_MPI_MIN_VERSION) | |
| # If the user specified a library name we assume they prefer that library over a wrapper. If not, they can disable skipping manually. | |
| if(NOT DEFINED MPI_SKIP_COMPILER_WRAPPER AND MPI_GUESS_LIBRARY_NAME) | |
| set(MPI_SKIP_COMPILER_WRAPPER TRUE) | |
| endif() | |
| # This loop finds the compilers and sends them off for interrogation. | |
| foreach(LANG IN ITEMS C CXX Fortran) | |
| if(CMAKE_${LANG}_COMPILER_LOADED) | |
| if(NOT MPI_FIND_COMPONENTS) | |
| set(_MPI_FIND_${LANG} TRUE) | |
| elseif( ${LANG} IN_LIST MPI_FIND_COMPONENTS) | |
| set(_MPI_FIND_${LANG} TRUE) | |
| elseif( ${LANG} STREQUAL CXX AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS ) | |
| set(_MPI_FIND_${LANG} TRUE) | |
| else() | |
| set(_MPI_FIND_${LANG} FALSE) | |
| endif() | |
| else() | |
| set(_MPI_FIND_${LANG} FALSE) | |
| if(${LANG} IN_LIST MPI_FIND_COMPONENTS) | |
| string(APPEND _MPI_FAIL_REASON "MPI component '${LANG}' was requested, but language ${LANG} is not enabled. ") | |
| endif() | |
| endif() | |
| if(_MPI_FIND_${LANG}) | |
| if( ${LANG} STREQUAL CXX AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS ) | |
| option(MPI_CXX_SKIP_MPICXX "If true, the MPI-2 C++ bindings are disabled using definitions." FALSE) | |
| mark_as_advanced(MPI_CXX_SKIP_MPICXX) | |
| endif() | |
| _MPI_adjust_compile_definitions(${LANG}) | |
| if(NOT (MPI_${LANG}_LIB_NAMES AND (MPI_${LANG}_INCLUDE_PATH OR MPI_${LANG}_INCLUDE_DIRS OR MPI_${LANG}_COMPILER_INCLUDE_DIRS))) | |
| set(MPI_${LANG}_TRIED_IMPLICIT FALSE) | |
| set(MPI_${LANG}_WORKS_IMPLICIT FALSE) | |
| if(NOT MPI_${LANG}_COMPILER AND NOT MPI_ASSUME_NO_BUILTIN_MPI) | |
| # Should the imported targets be empty, we effectively try whether the compiler supports MPI on its own, which is the case on e.g. | |
| # Cray PrgEnv. | |
| _MPI_create_imported_target(${LANG}) | |
| _MPI_check_lang_works(${LANG} TRUE) | |
| # If the compiler can build MPI code on its own, it functions as an MPI compiler and we'll set the variable to point to it. | |
| if(MPI_${LANG}_WORKS) | |
| set(MPI_${LANG}_COMPILER "${CMAKE_${LANG}_COMPILER}" CACHE FILEPATH "MPI compiler for ${LANG}" FORCE) | |
| set(MPI_${LANG}_WORKS_IMPLICIT TRUE) | |
| endif() | |
| set(MPI_${LANG}_TRIED_IMPLICIT TRUE) | |
| endif() | |
| if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_${LANG}_WORKS) | |
| set(MPI_${LANG}_WRAPPER_FOUND FALSE) | |
| set(MPI_PINNED_COMPILER FALSE) | |
| if(NOT MPI_SKIP_COMPILER_WRAPPER) | |
| if(MPI_${LANG}_COMPILER) | |
| # If the user supplies a compiler *name* instead of an absolute path, assume that we need to find THAT compiler. | |
| if (NOT IS_ABSOLUTE "${MPI_${LANG}_COMPILER}") | |
| # Get rid of our default list of names and just search for the name the user wants. | |
| set(_MPI_${LANG}_COMPILER_NAMES "${MPI_${LANG}_COMPILER}") | |
| unset(MPI_${LANG}_COMPILER CACHE) | |
| endif() | |
| # If the user specifies a compiler, we don't want to try to search libraries either. | |
| set(MPI_PINNED_COMPILER TRUE) | |
| endif() | |
| # If we have an MPI base directory, we'll try all compiler names in that one first. | |
| # This should prevent mixing different MPI environments | |
| if(_MPI_BASE_DIR) | |
| find_program(MPI_${LANG}_COMPILER | |
| NAMES ${_MPI_${LANG}_COMPILER_NAMES} | |
| PATH_SUFFIXES bin sbin | |
| HINTS ${_MPI_BASE_DIR} | |
| NO_DEFAULT_PATH | |
| DOC "MPI compiler for ${LANG}" | |
| ) | |
| endif() | |
| # If the base directory did not help (for example because the mpiexec isn't in the same directory as the compilers), | |
| # we shall try searching in the default paths. | |
| find_program(MPI_${LANG}_COMPILER | |
| NAMES ${_MPI_${LANG}_COMPILER_NAMES} | |
| PATH_SUFFIXES bin sbin | |
| DOC "MPI compiler for ${LANG}" | |
| ) | |
| if("${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") | |
| set(MPI_PINNED_COMPILER TRUE) | |
| # If we haven't made the implicit compiler test yet, perform it now. | |
| if(NOT MPI_${LANG}_TRIED_IMPLICIT) | |
| _MPI_create_imported_target(${LANG}) | |
| _MPI_check_lang_works(${LANG} TRUE) | |
| endif() | |
| # Should the MPI compiler not work implicitly for MPI, still interrogate it. | |
| # Otherwise, MPI compilers for which CMake has separate linking stages, e.g. Intel MPI on Windows where link.exe is being used | |
| # directly during linkage instead of CMAKE_<LANG>_COMPILER will not work. | |
| if(NOT MPI_${LANG}_WORKS) | |
| set(MPI_${LANG}_WORKS_IMPLICIT FALSE) | |
| _MPI_interrogate_compiler(${LANG}) | |
| else() | |
| set(MPI_${LANG}_WORKS_IMPLICIT TRUE) | |
| endif() | |
| elseif(MPI_${LANG}_COMPILER) | |
| _MPI_interrogate_compiler(${LANG}) | |
| endif() | |
| endif() | |
| # We are on a Cray, environment identfier: PE_ENV is set (CRAY), and | |
| # have NOT found an mpic++-like compiler wrapper (previous block), | |
| # and we do NOT use the Cray cc/CC compiler wrappers as CC/CXX CMake | |
| # compiler. | |
| # So as a last resort, we now interrogate cc/CC/ftn for MPI flags. | |
| if(DEFINED ENV{PE_ENV} AND NOT "${MPI_${LANG}_COMPILER}") | |
| set(MPI_PINNED_COMPILER TRUE) | |
| find_program(MPI_${LANG}_COMPILER | |
| NAMES ${_MPI_Cray_${LANG}_COMPILER_NAMES} | |
| PATH_SUFFIXES bin sbin | |
| DOC "MPI compiler for ${LANG}" | |
| ) | |
| # If we haven't made the implicit compiler test yet, perform it now. | |
| if(NOT MPI_${LANG}_TRIED_IMPLICIT) | |
| _MPI_create_imported_target(${LANG}) | |
| _MPI_check_lang_works(${LANG} TRUE) | |
| endif() | |
| set(MPI_${LANG}_WORKS_IMPLICIT TRUE) | |
| _MPI_interrogate_compiler(${LANG}) | |
| endif() | |
| if(NOT MPI_PINNED_COMPILER AND NOT MPI_${LANG}_WRAPPER_FOUND) | |
| # If MPI_PINNED_COMPILER wasn't given, and the MPI compiler we potentially found didn't work, we withdraw it. | |
| set(MPI_${LANG}_COMPILER "MPI_${LANG}_COMPILER-NOTFOUND" CACHE FILEPATH "MPI compiler for ${LANG}" FORCE) | |
| if(LANG STREQUAL "C") | |
| set(_MPI_PKG "mpi-c") | |
| elseif(LANG STREQUAL "CXX") | |
| set(_MPI_PKG "mpi-cxx") | |
| elseif(LANG STREQUAL "Fortran") | |
| set(_MPI_PKG "mpi-fort") | |
| else() | |
| set(_MPI_PKG "") | |
| endif() | |
| if(_MPI_PKG AND PKG_CONFIG_FOUND) | |
| pkg_check_modules("MPI_${LANG}_PKG" "${_MPI_PKG}") | |
| if("${MPI_${LANG}_PKG_FOUND}") | |
| set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_${LANG}_PKG_CFLAGS} CACHE STRING "MPI ${LANG} compilation options" FORCE) | |
| set(MPI_${LANG}_INCLUDE_PATH ${MPI_${LANG}_PKG_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} include directories" FORCE) | |
| set(MPI_${LANG}_LINK_FLAGS ${MPI_${LANG}_PKG_LDFLAGS} CACHE STRING "MPI ${LANG} linker flags" FORCE) | |
| set(MPI_${LANG}_LIB_NAMES ${MPI_${LANG}_PKG_LIBRARIES} CACHE STRING "MPI ${LANG} libraries to link against" FORCE) | |
| foreach(_MPI_LIB IN LISTS MPI_${LANG}_LIB_NAMES) | |
| if(_MPI_LIB) | |
| get_filename_component(_MPI_PLAIN_LIB_NAME "${_MPI_LIB}" NAME_WE) | |
| get_filename_component(_MPI_LIB_NAME "${_MPI_LIB}" NAME) | |
| get_filename_component(_MPI_LIB_DIR "${_MPI_LIB}" DIRECTORY) | |
| find_library(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY | |
| NAMES "${_MPI_LIB_NAME}" "lib${_MPI_LIB_NAME}" | |
| HINTS ${_MPI_LIB_DIR} | |
| DOC "Location of the ${_MPI_PLAIN_LIB_NAME} library for MPI" | |
| ) | |
| mark_as_advanced(MPI_${_MPI_PLAIN_LIB_NAME}_LIBRARY) | |
| endif() | |
| endforeach() | |
| endif() | |
| endif() | |
| if(NOT MPI_SKIP_GUESSING AND NOT "${MPI_${LANG}_PKG_FOUND}") | |
| # For C++, we may use the settings for C. Should a given compiler wrapper for C++ not exist, but one for C does, we copy over the | |
| # settings for C. An MPI distribution that is in this situation would be IBM Platform MPI. | |
| if("${LANG}" STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND) | |
| set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_C_COMPILE_OPTIONS} CACHE STRING "MPI ${LANG} compilation options" ) | |
| set(MPI_${LANG}_COMPILE_DEFINITIONS ${MPI_C_COMPILE_DEFINITIONS} CACHE STRING "MPI ${LANG} compilation definitions" ) | |
| set(MPI_${LANG}_COMPILER_INCLUDE_DIRS ${MPI_C_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} compiler wrapper include directories") | |
| set(MPI_${LANG}_LINK_FLAGS ${MPI_C_LINK_FLAGS} CACHE STRING "MPI ${LANG} linker flags" ) | |
| set(MPI_${LANG}_LIB_NAMES ${MPI_C_LIB_NAMES} CACHE STRING "MPI ${LANG} libraries to link against" ) | |
| else() | |
| _MPI_guess_settings(${LANG}) | |
| endif() | |
| endif() | |
| endif() | |
| endif() | |
| endif() | |
| if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") | |
| _MPI_split_include_dirs(${LANG}) | |
| _MPI_assemble_include_dirs(${LANG}) | |
| else() | |
| set(MPI_${LANG}_INCLUDE_DIRS "") | |
| endif() | |
| _MPI_assemble_libraries(${LANG}) | |
| # We always create imported targets even if they're empty | |
| _MPI_create_imported_target(${LANG}) | |
| if(NOT MPI_${LANG}_WORKS) | |
| _MPI_check_lang_works(${LANG} FALSE) | |
| endif() | |
| # Next, we'll initialize the MPI variables that have not been previously set. | |
| set(MPI_${LANG}_COMPILE_OPTIONS "" CACHE STRING "MPI ${LANG} compilation flags" ) | |
| set(MPI_${LANG}_COMPILE_DEFINITIONS "" CACHE STRING "MPI ${LANG} compilation definitions" ) | |
| set(MPI_${LANG}_COMPILER_INCLUDE_DIRS "" CACHE STRING "MPI ${LANG} compiler wrapper include directories") | |
| set(MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS "" CACHE STRING "MPI ${LANG} additional include directories") | |
| set(MPI_${LANG}_LINK_FLAGS "" CACHE STRING "MPI ${LANG} linker flags" ) | |
| if(NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER) | |
| set(MPI_${LANG}_LIB_NAMES "" CACHE STRING "MPI ${LANG} libraries to link against" ) | |
| endif() | |
| mark_as_advanced( | |
| MPI_${LANG}_COMPILE_OPTIONS | |
| MPI_${LANG}_COMPILE_DEFINITIONS | |
| MPI_${LANG}_LINK_FLAGS | |
| MPI_${LANG}_LIB_NAMES | |
| MPI_${LANG}_COMPILER_INCLUDE_DIRS | |
| MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS | |
| MPI_${LANG}_COMPILER | |
| ) | |
| # If we've found MPI, then we'll perform additional analysis: Determine the MPI version, MPI library version, supported | |
| # MPI APIs (i.e. MPI-2 C++ bindings). For Fortran we also need to find specific parameters if we're under MPI-3. | |
| if(MPI_${LANG}_WORKS) | |
| if("${LANG}" STREQUAL "CXX" AND NOT DEFINED MPI_MPICXX_FOUND) | |
| if(NOT MPI_CXX_SKIP_MPICXX AND NOT MPI_CXX_VALIDATE_SKIP_MPICXX) | |
| _MPI_try_staged_settings(${LANG} test_mpi MPICXX FALSE FALSE) | |
| if(MPI_RESULT_${LANG}_test_mpi_MPICXX) | |
| set(MPI_MPICXX_FOUND TRUE) | |
| else() | |
| set(MPI_MPICXX_FOUND FALSE) | |
| endif() | |
| else() | |
| set(MPI_MPICXX_FOUND FALSE) | |
| endif() | |
| endif() | |
| # At this point, we know the bindings present but not the MPI version or anything else. | |
| if(NOT DEFINED MPI_${LANG}_VERSION) | |
| unset(MPI_${LANG}_VERSION_MAJOR) | |
| unset(MPI_${LANG}_VERSION_MINOR) | |
| endif() | |
| set(MPI_BIN_FOLDER ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI) | |
| # For Fortran, we'll want to use the most modern MPI binding to test capabilities other than the | |
| # Fortran parameters, since those depend on the method of consumption. | |
| # For C++, we can always use the C bindings, and should do so, since the C++ bindings do not exist in MPI-3 | |
| # whereas the C bindings do, and the C++ bindings never offered any feature advantage over their C counterparts. | |
| if("${LANG}" STREQUAL "Fortran") | |
| if(MPI_${LANG}_HAVE_F08_MODULE) | |
| set(MPI_${LANG}_HIGHEST_METHOD F08_MODULE) | |
| elseif(MPI_${LANG}_HAVE_F90_MODULE) | |
| set(MPI_${LANG}_HIGHEST_METHOD F90_MODULE) | |
| else() | |
| set(MPI_${LANG}_HIGHEST_METHOD F77_HEADER) | |
| endif() | |
| # Another difference between C and Fortran is that we can't use the preprocessor to determine whether MPI_VERSION | |
| # and MPI_SUBVERSION are provided. These defines did not exist in MPI 1.0 and 1.1 and therefore might not | |
| # exist. For C/C++, test_mpi.c will handle the MPI_VERSION extraction, but for Fortran, we need mpiver.f90. | |
| if(NOT DEFINED MPI_${LANG}_VERSION) | |
| _MPI_try_staged_settings(${LANG} mpiver ${MPI_${LANG}_HIGHEST_METHOD} FALSE FALSE) | |
| if(MPI_RESULT_${LANG}_mpiver_${MPI_${LANG}_HIGHEST_METHOD}) | |
| file(STRINGS ${MPI_BIN_FOLDER}/mpiver_${LANG}.bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER") | |
| if("${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*") | |
| set(MPI_${LANG}_VERSION_MAJOR "${CMAKE_MATCH_1}") | |
| set(MPI_${LANG}_VERSION_MINOR "${CMAKE_MATCH_2}") | |
| set(MPI_${LANG}_VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}") | |
| endif() | |
| endif() | |
| endif() | |
| # Finally, we want to find out which capabilities a given interface supports, compare the MPI-3 standard. | |
| # This is determined by interface specific parameters MPI_SUBARRAYS_SUPPORTED and MPI_ASYNC_PROTECTS_NONBLOCKING | |
| # and might vary between the different methods of consumption. | |
| if(MPI_DETERMINE_Fortran_CAPABILITIES AND NOT MPI_Fortran_CAPABILITIES_DETERMINED) | |
| foreach(mpimethod IN ITEMS F08_MODULE F90_MODULE F77_HEADER) | |
| if(MPI_${LANG}_HAVE_${mpimethod}) | |
| set(MPI_${LANG}_${mpimethod}_SUBARRAYS FALSE) | |
| set(MPI_${LANG}_${mpimethod}_ASYNCPROT FALSE) | |
| _MPI_try_staged_settings(${LANG} fortranparam_mpi ${mpimethod} TRUE FALSE) | |
| if(MPI_RESULT_${LANG}_fortranparam_mpi_${mpimethod} AND | |
| NOT "${MPI_RUN_RESULT_${LANG}_fortranparam_mpi_${mpimethod}}" STREQUAL "FAILED_TO_RUN") | |
| if("${MPI_RUN_OUTPUT_${LANG}_fortranparam_mpi_${mpimethod}}" MATCHES | |
| ".*INFO:SUBARRAYS\\[ *([TF]) *\\]-ASYNCPROT\\[ *([TF]) *\\].*") | |
| if("${CMAKE_MATCH_1}" STREQUAL "T") | |
| set(MPI_${LANG}_${mpimethod}_SUBARRAYS TRUE) | |
| endif() | |
| if("${CMAKE_MATCH_2}" STREQUAL "T") | |
| set(MPI_${LANG}_${mpimethod}_ASYNCPROT TRUE) | |
| endif() | |
| endif() | |
| endif() | |
| endif() | |
| endforeach() | |
| set(MPI_Fortran_CAPABILITIES_DETERMINED TRUE) | |
| endif() | |
| else() | |
| set(MPI_${LANG}_HIGHEST_METHOD normal) | |
| # By the MPI-2 standard, MPI_VERSION and MPI_SUBVERSION are valid for both C and C++ bindings. | |
| if(NOT DEFINED MPI_${LANG}_VERSION) | |
| file(STRINGS ${MPI_BIN_FOLDER}/test_mpi_${LANG}.bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER") | |
| if("${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*") | |
| set(MPI_${LANG}_VERSION_MAJOR "${CMAKE_MATCH_1}") | |
| set(MPI_${LANG}_VERSION_MINOR "${CMAKE_MATCH_2}") | |
| set(MPI_${LANG}_VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}") | |
| endif() | |
| endif() | |
| endif() | |
| unset(MPI_BIN_FOLDER) | |
| # At this point, we have dealt with determining the MPI version and parameters for each Fortran method available. | |
| # The one remaining issue is to determine which MPI library is installed. | |
| # Determining the version and vendor of the MPI library is only possible via MPI_Get_library_version() at runtime, | |
| # and therefore we cannot do this while cross-compiling (a user may still define MPI_<lang>_LIBRARY_VERSION_STRING | |
| # themselves and we'll attempt splitting it, which is equivalent to provide the try_run output). | |
| # It's also worth noting that the installed version string can depend on the language, or on the system the binary | |
| # runs on if MPI is not statically linked. | |
| if(MPI_DETERMINE_LIBRARY_VERSION AND NOT MPI_${LANG}_LIBRARY_VERSION_STRING) | |
| _MPI_try_staged_settings(${LANG} libver_mpi ${MPI_${LANG}_HIGHEST_METHOD} TRUE FALSE) | |
| if(MPI_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD} AND | |
| "${MPI_RUN_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}" EQUAL "0") | |
| string(STRIP "${MPI_RUN_OUTPUT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}" | |
| MPI_${LANG}_LIBRARY_VERSION_STRING) | |
| else() | |
| set(MPI_${LANG}_LIBRARY_VERSION_STRING "NOTFOUND") | |
| endif() | |
| endif() | |
| endif() | |
| set(MPI_${LANG}_FIND_QUIETLY ${MPI_FIND_QUIETLY}) | |
| set(MPI_${LANG}_FIND_VERSION ${MPI_FIND_VERSION}) | |
| set(MPI_${LANG}_FIND_VERSION_EXACT ${MPI_FIND_VERSION_EXACT}) | |
| unset(MPI_${LANG}_REQUIRED_VARS) | |
| if (NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") | |
| foreach(mpilibname IN LISTS MPI_${LANG}_LIB_NAMES) | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${mpilibname}_LIBRARY") | |
| endforeach() | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_LIB_NAMES") | |
| if("${LANG}" STREQUAL "Fortran") | |
| # For Fortran we only need one of the module or header directories to have *some* support for MPI. | |
| if(NOT MPI_${LANG}_MODULE_DIR) | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_F77_HEADER_DIR") | |
| endif() | |
| if(NOT MPI_${LANG}_F77_HEADER_DIR) | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_MODULE_DIR") | |
| endif() | |
| else() | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_HEADER_DIR") | |
| endif() | |
| if(MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) | |
| foreach(mpiincvar IN LISTS MPI_${LANG}_ADDITIONAL_INCLUDE_VARS) | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${mpiincvar}_INCLUDE_DIR") | |
| endforeach() | |
| endif() | |
| # Append the works variable now. If the settings did not work, this will show up properly. | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_WORKS") | |
| else() | |
| # If the compiler worked implicitly, use its path as output. | |
| # Should the compiler variable be set, we also require it to work. | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_COMPILER") | |
| if(MPI_${LANG}_COMPILER) | |
| list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_WORKS") | |
| endif() | |
| endif() | |
| find_package_handle_standard_args(MPI_${LANG} NAME_MISMATCHED | |
| REQUIRED_VARS ${MPI_${LANG}_REQUIRED_VARS} | |
| VERSION_VAR MPI_${LANG}_VERSION) | |
| if(DEFINED MPI_${LANG}_VERSION) | |
| if(NOT _MPI_MIN_VERSION OR _MPI_MIN_VERSION VERSION_GREATER MPI_${LANG}_VERSION) | |
| set(_MPI_MIN_VERSION MPI_${LANG}_VERSION) | |
| endif() | |
| endif() | |
| endif() | |
| endforeach() | |
| unset(_MPI_REQ_VARS) | |
| foreach(LANG IN ITEMS C CXX Fortran) | |
| if((NOT MPI_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST MPI_FIND_COMPONENTS) | |
| list(APPEND _MPI_REQ_VARS "MPI_${LANG}_FOUND") | |
| endif() | |
| endforeach() | |
| if(MPICXX IN_LIST MPI_FIND_COMPONENTS) | |
| list(APPEND _MPI_REQ_VARS "MPI_MPICXX_FOUND") | |
| endif() | |
| find_package_handle_standard_args(MPI | |
| REQUIRED_VARS ${_MPI_REQ_VARS} | |
| VERSION_VAR ${_MPI_MIN_VERSION} | |
| REASON_FAILURE_MESSAGE "${_MPI_FAIL_REASON}" | |
| HANDLE_COMPONENTS) | |
| #============================================================================= | |
| # More backward compatibility stuff | |
| # For compatibility reasons, we also define MPIEXEC | |
| set(MPIEXEC "${MPIEXEC_EXECUTABLE}") | |
| # Copy over MPI_<LANG>_INCLUDE_PATH from the assembled INCLUDE_DIRS. | |
| foreach(LANG IN ITEMS C CXX Fortran) | |
| if(MPI_${LANG}_FOUND) | |
| set(MPI_${LANG}_INCLUDE_PATH "${MPI_${LANG}_INCLUDE_DIRS}") | |
| unset(MPI_${LANG}_COMPILE_FLAGS) | |
| if(MPI_${LANG}_COMPILE_OPTIONS) | |
| list(JOIN MPI_${LANG}_COMPILE_OPTIONS " " MPI_${LANG}_COMPILE_FLAGS) | |
| endif() | |
| if(MPI_${LANG}_COMPILE_DEFINITIONS) | |
| foreach(_MPI_DEF IN LISTS MPI_${LANG}_COMPILE_DEFINITIONS) | |
| string(APPEND MPI_${LANG}_COMPILE_FLAGS " -D${_MPI_DEF}") | |
| endforeach() | |
| endif() | |
| endif() | |
| endforeach() | |
| # Bare MPI sans ${LANG} vars are set to CXX then C, depending on what was found. | |
| # This mimics the behavior of the old language-oblivious FindMPI. | |
| set(_MPI_OLD_VARS COMPILER INCLUDE_PATH COMPILE_FLAGS LINK_FLAGS LIBRARIES) | |
| if (MPI_CXX_FOUND) | |
| foreach (var ${_MPI_OLD_VARS}) | |
| set(MPI_${var} ${MPI_CXX_${var}}) | |
| endforeach() | |
| elseif (MPI_C_FOUND) | |
| foreach (var ${_MPI_OLD_VARS}) | |
| set(MPI_${var} ${MPI_C_${var}}) | |
| endforeach() | |
| endif() | |
| # Chop MPI_LIBRARIES into the old-style MPI_LIBRARY and MPI_EXTRA_LIBRARY, and set them in cache. | |
| if (MPI_LIBRARIES) | |
| list(GET MPI_LIBRARIES 0 MPI_LIBRARY_WORK) | |
| set(MPI_LIBRARY "${MPI_LIBRARY_WORK}") | |
| unset(MPI_LIBRARY_WORK) | |
| else() | |
| set(MPI_LIBRARY "MPI_LIBRARY-NOTFOUND") | |
| endif() | |
| list(LENGTH MPI_LIBRARIES MPI_NUMLIBS) | |
| if (MPI_NUMLIBS GREATER 1) | |
| set(MPI_EXTRA_LIBRARY_WORK "${MPI_LIBRARIES}") | |
| list(REMOVE_AT MPI_EXTRA_LIBRARY_WORK 0) | |
| set(MPI_EXTRA_LIBRARY "${MPI_EXTRA_LIBRARY_WORK}") | |
| unset(MPI_EXTRA_LIBRARY_WORK) | |
| else() | |
| set(MPI_EXTRA_LIBRARY "MPI_EXTRA_LIBRARY-NOTFOUND") | |
| endif() | |
| set(MPI_IGNORE_LEGACY_VARIABLES TRUE) | |
| #============================================================================= | |
| # unset these vars to cleanup namespace | |
| unset(_MPI_OLD_VARS) | |
| unset(_MPI_PREFIX_PATH) | |
| unset(_MPI_BASE_DIR) | |
| foreach (lang C CXX Fortran) | |
| unset(_MPI_${LANG}_COMPILER_NAMES) | |
| endforeach() | |
| cmake_policy(POP) |