Skip to content

Commit 344ac30

Browse files
committed
CMake will build OpenCoarrays on windows w/ GCC & IMPI
The library now builds with Intel MPI (from Intel OneAPI) and GCC + GFortran. There are still some path handling quirks and string quoting things that need to be resolved to get the caf and cafrun wrapper scripts working reliably. A test program can be built and run by tweaking/fixing the commands attempted by the caf script. The program executes correctly and then encounters an error during MPI finalize/when shutting down.
1 parent cf4f9ab commit 344ac30

File tree

2 files changed

+148
-66
lines changed

2 files changed

+148
-66
lines changed

CMakeLists.txt

Lines changed: 134 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ endif()
204204

205205
if(CMAKE_BUILD_TYPE MATCHES "Debug|DEBUG|debug")
206206
add_definitions(-DEXTRA_DEBUG_OUTPUT)
207+
set(IMPI_BUILD debug)
208+
else()
209+
set(IMPI_BUILD release)
207210
endif()
208211

209212
# We have populated CMAKE_Fortran_COMPILER_VERSION if it was missing
@@ -274,102 +277,167 @@ if (C_COMPILER_NAME MATCHES "^[mM][pP][iI]")
274277
set (MPI_C_COMPILER "${CMAKE_C_COMPILER}")
275278
endif()
276279

277-
find_package( MPI )
280+
if(WIN32) # Only support building with GCC & GFortran using Intel MPI (OneAPI)
281+
# Here we assume Intel ONEAPI and the environment is loaded
282+
cmake_path(SET MPI_ROOT NORMALIZE "$ENV{I_MPI_ROOT}")
283+
set (IMPI_INCLUDES "${MPI_ROOT}/include")
284+
set (IMPI_LIB_DIR "${MPI_ROOT}/lib/${IMPI_BUILD}")
285+
set (IMPI_DLL_DIR "${MPI_ROOT}/bin/${IMPI_BUILD}")
286+
set (IMPI_BIN_DIR "${MPI_ROOT}/bin")
287+
288+
find_library(IMPI_LIB
289+
"impi.lib"
290+
HINTS "${IMPI_LIB_DIR}"
291+
DOC "Location of the Intel MPI impi.lib file"
292+
REQUIRED
293+
NO_DEFAULT_PATH)
294+
295+
set(MPI_impi_LIBRARY "${IMPI_LIB}")
296+
set(MPI_impicxx_LIBRARY "${IMPI_LIB_DIR}/impicxx.lib")
297+
298+
find_file(IMPI_DLL
299+
"impi.dll"
300+
HINTS "${IMPI_DLL_DIR}"
301+
DOC "Location of the Intel MPI impi.dll file"
302+
REQUIRED
303+
NO_DEFAULT_PATH)
304+
305+
306+
add_library(IMPI::MPI SHARED IMPORTED)
307+
set_target_properties(IMPI::MPI
308+
PROPERTIES
309+
IMPORTED_IMPLIB "${IMPI_LIB}"
310+
IMPORTED_LOCATION "${IMPI_DLL}")
311+
target_include_directories(IMPI::MPI
312+
INTERFACE "${IMPI_INCLUDES}")
313+
314+
set(MPI_C_INCLUDE_DIRS "${IMPI_INCLUDES}")
315+
set(MPI_C_INCLUDE_PATH "${IMPI_INCLUDES}")
316+
set(MPI_C_HEADER_DIR "${IMPI_INCLUDES}")
317+
set(MPI_Fortran_COMPILER_INCLUDE_DIRS "${IMPI_INCLUDES}")
318+
set(MPI_Fortran_F77_HEADER_DIR "${IMPI_INCLUDES}")
319+
set(MPI_Fortran_INCLUDE_PATH "${IMPI_INCLUDES}")
320+
321+
set(MPI_C_LIB_NAMES impi;impicxx)
322+
set(MPI_C_LIBRARIES "${IMPI_LIB}")
323+
set(MPI_Fortran_LIB_NAMES impi)
324+
set(MPI_Fortran_LIBRARIES "${IMPI_LIB}")
325+
326+
set(MPI_Fortran_HAVE_F90_MODULE FALSE)
327+
set(MPI_Fortran_HAVE_F08_MODULE FALSE)
328+
329+
find_program(MPIEXEC_EXECUTABLE
330+
mpiexec
331+
HINTS "${IMPI_BIN_DIR}"
332+
DOC "Location of Intel MPI implementations mpiexec launcher program"
333+
REQUIRED
334+
NO_DEFAULT_PATH)
335+
set(MPIEXEC "${MPIEXEC_EXECUTABLE}")
336+
set(MPI_EXEC_NUMPROC_FLAG -n)
337+
set(MPI_EXEC_PREFLAGS -print-all-exitcodes)
338+
339+
set(MPI_C_FOUND TRUE)
340+
set(MPI_Fortran_FOUND TRUE)
341+
342+
else()
343+
find_package( MPI )
278344

279-
if ( (NOT MPI_C_FOUND) OR (NOT MPI_Fortran_FOUND) OR (NOT MPIEXEC))
280-
# Get default install location of MPICH from install.sh
281-
message(WARNING "Could not find all MPI components!")
282-
message(WARNING "
345+
if ( (NOT MPI_C_FOUND) OR (NOT MPI_Fortran_FOUND) OR (NOT MPIEXEC_EXECUTABLE))
346+
# Get default install location of MPICH from install.sh
347+
message(WARNING "Could not find all MPI components!")
348+
message(WARNING "
283349
MPI_C_FOUND = ${MPI_C_FOUND}
284350
MPI_Fortran_FOUND = ${MPI_Fortran_FOUND}
285-
MPIEXEC = ${MPIEXEC}
351+
MPIEXEC = ${MPIEXEC_EXECUTABLE}
286352
")
287-
execute_process( COMMAND "./install.sh" -P mpich
288-
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
289-
OUTPUT_VARIABLE DEFAULT_MPICH_INSTALL_LOC
290-
OUTPUT_QUIET
291-
OUTPUT_STRIP_TRAILING_WHITESPACE
292-
)
293-
find_program (MY_MPI_EXEC NAMES mpirun mpiexec lamexec srun
294-
PATHS "${DEFAULT_MPICH_INSTALL_LOC}" ENV PATH
295-
HINTS "${FTN_COMPILER_DIR}" "${C_COMPILER_DIR}"
296-
PATH_SUFFIXES bin)
297-
set ( MPI_HOME "${MPI_HOME}" "${MY_MPI_EXEC}" "${MY_MPI_EXEC}/.." )
298-
find_package( MPI REQUIRED )
353+
execute_process( COMMAND "./install.sh" -P mpich
354+
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
355+
OUTPUT_VARIABLE DEFAULT_MPICH_INSTALL_LOC
356+
OUTPUT_QUIET
357+
OUTPUT_STRIP_TRAILING_WHITESPACE
358+
)
359+
find_program (MY_MPI_EXEC NAMES mpirun mpiexec lamexec srun
360+
PATHS "${DEFAULT_MPICH_INSTALL_LOC}" ENV PATH
361+
HINTS "${FTN_COMPILER_DIR}" "${C_COMPILER_DIR}"
362+
PATH_SUFFIXES bin)
363+
set ( MPI_HOME "${MPI_HOME}" "${MY_MPI_EXEC}" "${MY_MPI_EXEC}/.." )
364+
find_package( MPI REQUIRED )
365+
endif()
299366
endif()
300367
list(REMOVE_DUPLICATES MPI_Fortran_INCLUDE_PATH)
301368

302-
# Test for consistent MPI environment
303-
if (NOT MPIEXEC)
369+
# Test for consistent MPI environment but not on windows
370+
if (NOT MPIEXEC_EXECUTABLE)
304371
message ( ERROR "CMake failed to find `mpiexec` or similar. If building with `./install.sh` please
305372
report this bug to the OpenCoarrays developers at
306373
https://github.com/sourceryinstitute/opencoarrays/issues, otherwise point CMake
307374
to the desired MPI runtime.")
308375
else()
309376
add_definitions(-DHAVE_MPI)
310377
endif()
311-
312-
get_filename_component(MPIEXEC_RELATIVE_LOC "${MPIEXEC}"
313-
PROGRAM)
314-
get_filename_component(MPIEXEC_ABS_LOC "${MPIEXEC_RELATIVE_LOC}"
315-
REALPATH)
316-
get_filename_component(MPIEXEC_DIR "${MPIEXEC_ABS_LOC}"
317-
DIRECTORY)
318-
319-
get_filename_component(MPICC_RELATIVE_LOC "${MPI_C_COMPILER}"
320-
PROGRAM)
321-
get_filename_component(MPICC_ABS_LOC "${MPICC_RELATIVE_LOC}"
322-
REALPATH)
323-
get_filename_component(MPICC_DIR "${MPICC_ABS_LOC}"
324-
DIRECTORY)
325-
326-
get_filename_component(MPIFC_RELATIVE_LOC "${MPI_Fortran_COMPILER}"
327-
PROGRAM)
328-
get_filename_component(MPIFC_ABS_LOC "${MPIFC_RELATIVE_LOC}"
329-
REALPATH)
330-
get_filename_component(MPIFC_DIR "${MPIFC_ABS_LOC}"
331-
DIRECTORY)
332-
333-
if ((MPIEXEC_DIR STREQUAL MPICC_DIR) AND (MPIEXEC_DIR STREQUAL MPIFC_DIR))
334-
message ( STATUS "MPI runtime and compile time environments appear to be consistent")
335-
else()
336-
message ( WARNING "MPIEXEC is in \"${MPIEXEC_DIR},\"
378+
if(NOT WIN32)
379+
get_filename_component(MPIEXEC_RELATIVE_LOC "${MPIEXEC}"
380+
PROGRAM)
381+
get_filename_component(MPIEXEC_ABS_LOC "${MPIEXEC_RELATIVE_LOC}"
382+
REALPATH)
383+
get_filename_component(MPIEXEC_DIR "${MPIEXEC_ABS_LOC}"
384+
DIRECTORY)
385+
386+
get_filename_component(MPICC_RELATIVE_LOC "${MPI_C_COMPILER}"
387+
PROGRAM)
388+
get_filename_component(MPICC_ABS_LOC "${MPICC_RELATIVE_LOC}"
389+
REALPATH)
390+
get_filename_component(MPICC_DIR "${MPICC_ABS_LOC}"
391+
DIRECTORY)
392+
393+
get_filename_component(MPIFC_RELATIVE_LOC "${MPI_Fortran_COMPILER}"
394+
PROGRAM)
395+
get_filename_component(MPIFC_ABS_LOC "${MPIFC_RELATIVE_LOC}"
396+
REALPATH)
397+
get_filename_component(MPIFC_DIR "${MPIFC_ABS_LOC}"
398+
DIRECTORY)
399+
400+
if ((MPIEXEC_DIR STREQUAL MPICC_DIR) AND (MPIEXEC_DIR STREQUAL MPIFC_DIR))
401+
message ( STATUS "MPI runtime and compile time environments appear to be consistent")
402+
else()
403+
message ( WARNING "MPIEXEC is in \"${MPIEXEC_DIR},\"
337404
which differs from the location of MPICC and/or MPIFC which are in
338405
\"${MPICC_DIR}\" and \"${MPIFC_DIR},\" respectively.
339406
This is likely indicative of a problem. If building with `./install.sh` please report
340407
this to the OpenCoarrays developers by filing a new issue at:
341408
https://github.com/sourceryinstitute/OpenCoarrays/issues/new")
342-
endif()
409+
endif()
343410

344-
#-----------------------------------------------
345-
# Work around bug #317 present on fedora systems
346-
#-----------------------------------------------
347-
if( (MPI_C_LINK_FLAGS MATCHES "noexecstack") OR (MPI_Fortran_LINK_FLAGS MATCHES "noexecstack") )
348-
message ( WARNING
349-
"The `noexecstack` linker flag was found in the MPI_<lang>_LINK_FLAGS variable. This is
411+
#-----------------------------------------------
412+
# Work around bug #317 present on fedora systems
413+
#-----------------------------------------------
414+
if( (MPI_C_LINK_FLAGS MATCHES "noexecstack") OR (MPI_Fortran_LINK_FLAGS MATCHES "noexecstack") )
415+
message ( WARNING
416+
"The `noexecstack` linker flag was found in the MPI_<lang>_LINK_FLAGS variable. This is
350417
known to cause segmentation faults for some Fortran codes. See, e.g.,
351418
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71729 or
352419
https://github.com/sourceryinstitute/OpenCoarrays/issues/317.
353420
354421
`noexecstack` is being replaced with `execstack`"
355-
)
356-
string(REPLACE "noexecstack"
357-
"execstack" MPI_C_LINK_FLAGS_FIXED ${MPI_C_LINK_FLAGS})
358-
string(REPLACE "noexecstack"
359-
"execstack" MPI_Fortran_LINK_FLAGS_FIXED ${MPI_Fortran_LINK_FLAGS})
360-
set(MPI_C_LINK_FLAGS "${MPI_C_LINK_FLAGS_FIXED}" CACHE STRING
361-
"MPI C linking flags" FORCE)
362-
set(MPI_Fortran_LINK_FLAGS "${MPI_Fortran_LINK_FLAGS_FIXED}" CACHE STRING
363-
"MPI Fortran linking flags" FORCE)
422+
)
423+
string(REPLACE "noexecstack"
424+
"execstack" MPI_C_LINK_FLAGS_FIXED ${MPI_C_LINK_FLAGS})
425+
string(REPLACE "noexecstack"
426+
"execstack" MPI_Fortran_LINK_FLAGS_FIXED ${MPI_Fortran_LINK_FLAGS})
427+
set(MPI_C_LINK_FLAGS "${MPI_C_LINK_FLAGS_FIXED}" CACHE STRING
428+
"MPI C linking flags" FORCE)
429+
set(MPI_Fortran_LINK_FLAGS "${MPI_Fortran_LINK_FLAGS_FIXED}" CACHE STRING
430+
"MPI Fortran linking flags" FORCE)
431+
endif()
364432
endif()
365433

366434
#--------------------------------------------------------
367435
# Make sure a simple "hello world" C mpi program compiles
368436
#--------------------------------------------------------
369437
set(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
370-
set(CMAKE_REQUIRED_FLAGS ${MPI_C_COMPILE_FLAGS} ${MPI_C_LINK_FLAGS})
438+
set(CMAKE_REQUIRED_FLAGS ${MPI_C_COMPILE_OPTIONS} ${MPI_C_COMPILE_DEFINITIONS} ${MPI_C_LINK_FLAGS})
371439
set(OLD_INCLUDES ${CMAKE_REQUIRED_INCLUDES})
372-
set(CMAKE_REQUIRED_INCLUDES ${MPI_C_INCLUDE_PATH})
440+
set(CMAKE_REQUIRED_INCLUDES ${MPI_C_INCLUDE_DIRS})
373441
set(OLD_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
374442
set(CMAKE_REQUIRED_LIBRARIES ${MPI_C_LIBRARIES})
375443
include (CheckCSourceCompiles)
@@ -410,7 +478,7 @@ endif()
410478
# Try using mpi.mod first then fall back on includ 'mpif.h'
411479
#--------------------------------------------------------------
412480
set(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
413-
set(CMAKE_REQUIRED_FLAGS "-ffree-form" ${MPI_Fortran_COMPILE_FLAGS} ${MPI_Fortran_LINK_FLAGS})
481+
set(CMAKE_REQUIRED_FLAGS "-ffree-form" ${MPI_Fortran_COMPILE_OPTIONS} ${MPI_Fortran_COMPILE_DEFINITIONS} ${MPI_Fortran_LINK_FLAGS})
414482
set(OLD_INCLUDES ${CMAKE_REQUIRED_INCLUDES})
415483
set(CMAKE_REQUIRED_INCLUDES ${MPI_Fortran_INCLUDE_PATH})
416484
set(OLD_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
@@ -442,7 +510,7 @@ unset(OLD_LIBRARIES)
442510
# If that failed try using mpif.h
443511
#--------------------------------
444512
set(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
445-
set(CMAKE_REQUIRED_FLAGS "-ffree-form" ${MPI_Fortran_COMPILE_FLAGS} ${MPI_Fortran_LINK_FLAGS})
513+
set(CMAKE_REQUIRED_FLAGS "-ffree-form" ${MPI_Fortran_COMPILE_OPTIONS} ${MPI_Fortra_COMPILE_DEFINITIONS} ${MPI_Fortran_LINK_FLAGS})
446514
set(OLD_INCLUDES ${CMAKE_REQUIRED_INCLUDES})
447515
set(CMAKE_REQUIRED_INCLUDES ${MPI_Fortran_INCLUDE_PATH})
448516
set(OLD_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})

src/mpi/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ target_link_libraries(caf_mpi_static
4646
set_target_properties(caf_mpi_static
4747
PROPERTIES
4848
POSITION_INDEPENDENT_CODE TRUE)
49+
if(WIN32)
50+
target_compile_options(caf_mpi
51+
PUBLIC -pthread)
52+
target_link_libraries(caf_mpi
53+
PRIVATE pthread)
54+
set_target_properties(caf_mpi
55+
PROPERTIES LINKER_LANGUAGE Fortran)
56+
target_compile_options(caf_mpi_static
57+
PUBLIC -pthread)
58+
target_link_options(caf_mpi_static
59+
PUBLIC -pthread)
60+
target_link_libraries(caf_mpi_static
61+
PRIVATE gfortran)
62+
endif()
4963
target_include_directories(caf_mpi PUBLIC
5064
$<$<COMPILE_LANGUAGE:C>:${MPI_C_INCLUDE_PATH}>
5165
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src>

0 commit comments

Comments
 (0)