From 767553674ed025351c8ce6fd68511a6d28cf0c95 Mon Sep 17 00:00:00 2001 From: Christian Pfeiffer Date: Thu, 25 Jan 2018 17:27:02 +0100 Subject: FindMPI: Set up environment variables for wrapper For MPICH derivates and Intel MPI, we can improve the compiler wrapper behavior and accuracy by defining certain environment variables if they haven't been set otherwise. --- Modules/FindMPI.cmake | 85 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index c644815..3d2397d 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -357,6 +357,21 @@ function (_MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE) 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) @@ -368,6 +383,41 @@ function (_MPI_interrogate_compiler LANG) 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 @@ -408,6 +458,25 @@ function (_MPI_interrogate_compiler LANG) _MPI_check_compiler(${LANG} "-showme" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) 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) @@ -424,7 +493,6 @@ function (_MPI_interrogate_compiler LANG) # 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) - string(TOLOWER) foreach(_MPI_VARIABLE IN ITEMS COMPILE LINK) string(REGEX REPLACE "(^| )/" "\\1-" MPI_${_MPI_VARIABLE}_CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}") string(REPLACE "-libpath:" "-LIBPATH:" MPI_${_MPI_VARIABLE}_CMDLINE "${MPI_${_MPI_VARIABLE}_CMDLINE}") @@ -483,7 +551,7 @@ function (_MPI_interrogate_compiler LANG) # 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. - if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f(stack-protector|(no-|)strict-aliasing|PI[CE]|pi[ce])") + if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce])") list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}") endif() endforeach() @@ -515,6 +583,8 @@ function (_MPI_interrogate_compiler 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) @@ -666,10 +736,15 @@ function (_MPI_interrogate_compiler LANG) # Add the link directories given explicitly that we haven't used back as linker directories. 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}") + 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}") + set(MPI_LINK_FLAGS_WORK "${CMAKE_LIBRARY_PATH_FLAG}${_MPI_LINK_DIRECTORY_ACTUAL}") endif() endforeach() @@ -1204,7 +1279,7 @@ if(NOT MPI_IGNORE_LEGACY_VARIABLES) 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]([^ ]+)") + 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}") -- cgit v0.12