Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 64 additions & 29 deletions cmake/thirdparty/BLTSetupMPI.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ set(_mpi_compile_flags )
set(_mpi_includes )
set(_mpi_libraries )
set(_mpi_link_flags )
set(_mpi_fortran_includes )

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@white238 I told the agent that our C++ codes make heavy use of the C MPI API, so to focus on splitting out the C/C++ vs the Fortran paths and flags.

It said in many MPI installs the MPI_C_INCLUDE_DIRS and MPI_CXX_INCLUDE_DIRS are identical, but if its a concern, another option is to have the C++ get both C and CXX mpi flags and paths, de-duplicated.


macro(blt_append_mpi_language_flags output_var language)
foreach(_mpi_flag ${ARGN})
if(_mpi_flag)
list(APPEND ${output_var} "$<$<COMPILE_LANGUAGE:${language}>:${_mpi_flag}>")
endif()
endforeach()
endmacro()

macro(blt_append_mpi_cuda_host_flags output_var)
foreach(_mpi_flag ${ARGN})
if(_mpi_flag)
list(APPEND ${output_var} "$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=${_mpi_flag}>")
endif()
endforeach()
endmacro()

macro(blt_append_mpi_language_includes output_var language)
foreach(_mpi_include ${ARGN})
if(_mpi_include)
list(APPEND ${output_var} "$<$<COMPILE_LANGUAGE:${language}>:${_mpi_include}>")
endif()
endforeach()
endmacro()


if(BLT_ENABLE_FIND_MPI)
Expand All @@ -49,45 +74,54 @@ if (BLT_ENABLE_FIND_MPI)
#-------------------
# Compile flags
#-------------------
set(_c_flag ${MPI_C_${_mpi_compile_flags_suffix}})
if (_c_flag AND BLT_ENABLE_CUDA)
list(APPEND _mpi_compile_flags
$<$<NOT:$<COMPILE_LANGUAGE:CUDA>>:${_c_flag}>
$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=${_c_flag}>)
else()
list(APPEND _mpi_compile_flags ${_c_flag})
endif()
set(_c_flags ${MPI_C_${_mpi_compile_flags_suffix}})
blt_append_mpi_language_flags(_mpi_compile_flags C ${_c_flags})

set(_cxx_flag ${MPI_CXX_${_mpi_compile_flags_suffix}})
if (_cxx_flag AND NOT "${_c_flag}" STREQUAL "${_cxx_flag}")
if (BLT_ENABLE_CUDA)
list(APPEND _mpi_compile_flags
$<$<NOT:$<COMPILE_LANGUAGE:CUDA>>:${_cxx_flag}>
$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=${_cxx_flag}>)
else()
list(APPEND _mpi_compile_flags ${_cxx_flag})
endif()
set(_cxx_flags ${MPI_CXX_${_mpi_compile_flags_suffix}})
blt_append_mpi_language_flags(_mpi_compile_flags CXX ${_cxx_flags})

if (BLT_ENABLE_CUDA)
set(_cuda_host_flags ${_c_flags} ${_cxx_flags})
blt_list_remove_duplicates(TO _cuda_host_flags)
blt_append_mpi_cuda_host_flags(_mpi_compile_flags ${_cuda_host_flags})
endif()

if (BLT_ENABLE_FORTRAN)
set(_f_flag ${MPI_Fortran_${_mpi_compile_flags_suffix}})
if (_f_flag AND NOT "${_c_flag}" STREQUAL "${_f_flag}")
list(APPEND _mpi_compile_flags ${_f_flag})
endif()
set(_fortran_flags ${MPI_Fortran_${_mpi_compile_flags_suffix}})
blt_append_mpi_language_flags(_mpi_compile_flags Fortran ${_fortran_flags})
endif()
unset(_c_flag)
unset(_cxx_flag)
unset(_f_flag)
unset(_c_flags)
unset(_cxx_flags)
unset(_cuda_host_flags)
unset(_fortran_flags)

#-------------------
# Include paths
#-------------------
list(APPEND _mpi_includes ${MPI_C_${_mpi_includes_suffix}}
${MPI_CXX_${_mpi_includes_suffix}})
set(_c_includes ${MPI_C_${_mpi_includes_suffix}})
blt_list_remove_duplicates(TO _c_includes)
blt_append_mpi_language_includes(_mpi_includes C ${_c_includes})

set(_cxx_includes ${MPI_CXX_${_mpi_includes_suffix}})
blt_list_remove_duplicates(TO _cxx_includes)
blt_append_mpi_language_includes(_mpi_includes CXX ${_cxx_includes})

if (BLT_ENABLE_CUDA)
set(_cuda_includes ${_cxx_includes})
if (NOT _cuda_includes)
set(_cuda_includes ${_c_includes})
endif()
blt_append_mpi_language_includes(_mpi_includes CUDA ${_cuda_includes})
endif()

if (BLT_ENABLE_FORTRAN)
list(APPEND _mpi_includes ${MPI_Fortran_${_mpi_includes_suffix}})
set(_mpi_fortran_includes ${MPI_Fortran_${_mpi_includes_suffix}})
blt_list_remove_duplicates(TO _mpi_fortran_includes)
blt_append_mpi_language_includes(_mpi_includes Fortran ${_mpi_fortran_includes})
endif()
blt_list_remove_duplicates(TO _mpi_includes)
unset(_c_includes)
unset(_cxx_includes)
unset(_cuda_includes)

#-------------------
# Link flags
Expand Down Expand Up @@ -134,6 +168,7 @@ if (BLT_MPI_COMPILE_FLAGS)
endif()
if (BLT_MPI_INCLUDES)
set(_mpi_includes ${BLT_MPI_INCLUDES})
set(_mpi_fortran_includes ${BLT_MPI_INCLUDES})
endif()
if (BLT_MPI_LIBRARIES)
set(_mpi_libraries ${BLT_MPI_LIBRARIES})
Expand Down Expand Up @@ -170,7 +205,7 @@ if (BLT_ENABLE_FORTRAN)
# Determine if we should use fortran mpif.h header or fortran mpi module
find_path(mpif_path
NAMES "mpif.h"
PATHS ${_mpi_includes}
PATHS ${_mpi_fortran_includes}
NO_DEFAULT_PATH
)

Expand Down
26 changes: 26 additions & 0 deletions tests/projects/mpi-mixed-language/base/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.14)

project(mpi-mixed-language LANGUAGES CXX)

set(BLT_CXX_STD c++14 CACHE STRING "")
set(ENABLE_MPI On CACHE BOOL "")
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../fake_mpi")

include(${BLT_SOURCE_DIR}/SetupBLT.cmake)

blt_install_tpl_setups(DESTINATION lib/cmake/${PROJECT_NAME})

blt_add_library(
NAME mpi-mixed-language
SOURCES mpi-mixed-language.cpp
DEPENDS_ON blt::mpi)

install(TARGETS mpi-mixed-language
EXPORT mpi-mixed-language-targets)

install(FILES
${PROJECT_SOURCE_DIR}/mpi-mixed-language-config.cmake
DESTINATION lib/cmake/mpi-mixed-language)

install(EXPORT mpi-mixed-language-targets
DESTINATION lib/cmake/mpi-mixed-language)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include("${CMAKE_CURRENT_LIST_DIR}/mpi-mixed-language-targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/BLTSetupTargets.cmake")
13 changes: 13 additions & 0 deletions tests/projects/mpi-mixed-language/base/mpi-mixed-language.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <mpi.h>

#ifndef BLT_FAKE_MPI_CXX_HEADER
#error "Expected the fake CXX MPI include directory"
#endif

#ifndef BLT_FAKE_MPI_CXX_COMPILE_OPTION
#error "Expected the fake CXX MPI compile option"
#endif

void blt_mpi_mixed_language()
{
}
77 changes: 77 additions & 0 deletions tests/projects/mpi-mixed-language/downstream/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
foreach(_option MPI CUDA HIP OPENMP)
unset(ENABLE_${_option} CACHE)
unset(ENABLE_${_option})
endforeach()

cmake_minimum_required(VERSION 3.14)

project(mpi-mixed-language-user LANGUAGES CXX Fortran)

list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../fake_mpi")

find_package(mpi-mixed-language REQUIRED
NO_DEFAULT_PATH
PATHS ${base_install_dir}/lib/cmake/mpi-mixed-language)

set(_fake_mpi_root "${CMAKE_CURRENT_LIST_DIR}/../fake_mpi")
get_filename_component(_fake_mpi_root "${_fake_mpi_root}" ABSOLUTE)

function(_require_property_item target property expected)
get_target_property(_items ${target} ${property})
if(NOT _items)
message(FATAL_ERROR "Expected ${target} to have ${property}")
endif()

if(NOT "${expected}" IN_LIST _items)
message(FATAL_ERROR
"Expected ${target} ${property} to contain '${expected}', "
"but got '${_items}'")
endif()
endfunction()

function(_reject_raw_property_item target property unexpected)
get_target_property(_items ${target} ${property})
if(NOT _items)
return()
endif()

if("${unexpected}" IN_LIST _items)
message(FATAL_ERROR
"Expected ${target} ${property} not to contain unguarded item "
"'${unexpected}', but got '${_items}'")
endif()
endfunction()

set(_c_include "${_fake_mpi_root}/include/c")
set(_cxx_include "${_fake_mpi_root}/include/cxx")
set(_fortran_include "${_fake_mpi_root}/include/fortran")

_require_property_item(mpi INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
"$<$<COMPILE_LANGUAGE:C>:${_c_include}>")
_require_property_item(mpi INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
"$<$<COMPILE_LANGUAGE:CXX>:${_cxx_include}>")
_require_property_item(mpi INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
"$<$<COMPILE_LANGUAGE:Fortran>:${_fortran_include}>")

_reject_raw_property_item(mpi INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_c_include}")
_reject_raw_property_item(mpi INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_cxx_include}")
_reject_raw_property_item(mpi INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${_fortran_include}")

_require_property_item(mpi INTERFACE_COMPILE_OPTIONS
"$<$<COMPILE_LANGUAGE:C>:-DBLT_FAKE_MPI_C_COMPILE_OPTION>")
_require_property_item(mpi INTERFACE_COMPILE_OPTIONS
"$<$<COMPILE_LANGUAGE:CXX>:-DBLT_FAKE_MPI_CXX_COMPILE_OPTION>")
_require_property_item(mpi INTERFACE_COMPILE_OPTIONS
"$<$<COMPILE_LANGUAGE:Fortran>:-DBLT_FAKE_MPI_FORTRAN_COMPILE_OPTION>")

_reject_raw_property_item(mpi INTERFACE_COMPILE_OPTIONS "-DBLT_FAKE_MPI_C_COMPILE_OPTION")
_reject_raw_property_item(mpi INTERFACE_COMPILE_OPTIONS "-DBLT_FAKE_MPI_CXX_COMPILE_OPTION")
_reject_raw_property_item(mpi INTERFACE_COMPILE_OPTIONS "-DBLT_FAKE_MPI_FORTRAN_COMPILE_OPTION")

add_executable(mpi-mixed-language-user mpi-mixed-language-user.F)
target_link_libraries(mpi-mixed-language-user PUBLIC mpi-mixed-language mpi)

set_source_files_properties(
mpi-mixed-language-user.F
PROPERTIES
Fortran_FORMAT FREE)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef BLT_FAKE_MPI_FORTRAN_COMPILE_OPTION
#error "Expected the fake Fortran MPI compile option"
#endif

program fortran_test
include 'mpif.h'

if (blt_fake_mpi_fortran_header .ne. 1) stop 1

end program fortran_test
40 changes: 40 additions & 0 deletions tests/projects/mpi-mixed-language/fake_mpi/FindMPI.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright (c) 2017-2025, Lawrence Livermore National Security, LLC and
# other BLT Project Developers. See the top-level LICENSE file for details
#
# SPDX-License-Identifier: (BSD-3-Clause)

set(_fake_mpi_root "${CMAKE_CURRENT_LIST_DIR}")

set(MPI_FOUND TRUE)
set(MPI_C_FOUND TRUE)
set(MPI_CXX_FOUND TRUE)
set(MPI_Fortran_FOUND TRUE)

set(MPIEXEC_EXECUTABLE "${CMAKE_COMMAND}")
set(MPIEXEC "${CMAKE_COMMAND}")
set(MPIEXEC_NUMPROC_FLAG "-E")

set(MPI_C_INCLUDE_DIRS "${_fake_mpi_root}/include/c")
set(MPI_CXX_INCLUDE_DIRS "${_fake_mpi_root}/include/cxx")
set(MPI_Fortran_INCLUDE_DIRS "${_fake_mpi_root}/include/fortran")

set(MPI_C_INCLUDE_PATH "${MPI_C_INCLUDE_DIRS}")
set(MPI_CXX_INCLUDE_PATH "${MPI_CXX_INCLUDE_DIRS}")
set(MPI_Fortran_INCLUDE_PATH "${MPI_Fortran_INCLUDE_DIRS}")

set(MPI_C_COMPILE_OPTIONS "-DBLT_FAKE_MPI_C_COMPILE_OPTION")
set(MPI_CXX_COMPILE_OPTIONS "-DBLT_FAKE_MPI_CXX_COMPILE_OPTION")
set(MPI_Fortran_COMPILE_OPTIONS "-DBLT_FAKE_MPI_FORTRAN_COMPILE_OPTION")

set(MPI_C_COMPILE_FLAGS "${MPI_C_COMPILE_OPTIONS}")
set(MPI_CXX_COMPILE_FLAGS "${MPI_CXX_COMPILE_OPTIONS}")
set(MPI_Fortran_COMPILE_FLAGS "${MPI_Fortran_COMPILE_OPTIONS}")

set(MPI_C_LINK_FLAGS "")
set(MPI_CXX_LINK_FLAGS "")
set(MPI_Fortran_LINK_FLAGS "")
set(MPI_C_LIBRARIES "")
set(MPI_CXX_LIBRARIES "")
set(MPI_Fortran_LIBRARIES "")

unset(_fake_mpi_root)
6 changes: 6 additions & 0 deletions tests/projects/mpi-mixed-language/fake_mpi/include/c/mpi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef BLT_TEST_FAKE_MPI_C_MPI_H
#define BLT_TEST_FAKE_MPI_C_MPI_H

#define BLT_FAKE_MPI_C_HEADER 1

#endif
48 changes: 48 additions & 0 deletions tests/projects/mpi-mixed-language/fake_mpi/include/cxx/mpi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#ifndef BLT_TEST_FAKE_MPI_CXX_MPI_H
#define BLT_TEST_FAKE_MPI_CXX_MPI_H

#define BLT_FAKE_MPI_CXX_HEADER 1

typedef int MPI_Comm;
typedef int MPI_Datatype;
typedef int MPI_Op;

#define MPI_COMM_WORLD 0
#define MPI_INT 0
#define MPI_SUM 0

static inline int MPI_Init(int *, char ***)
{
return 0;
}

static inline int MPI_Comm_rank(MPI_Comm, int *rank)
{
*rank = 0;
return 0;
}

static inline int MPI_Comm_size(MPI_Comm, int *size)
{
*size = 4;
return 0;
}

static inline int MPI_Reduce(const void *sendbuf,
void *recvbuf,
int,
MPI_Datatype,
MPI_Op,
int,
MPI_Comm)
{
*static_cast<int *>(recvbuf) = *static_cast<const int *>(sendbuf) * 4;
return 0;
}

static inline int MPI_Finalize()
{
return 0;
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
integer, parameter :: blt_fake_mpi_fortran_header = 1
Loading