Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows support #755

Merged
merged 18 commits into from
May 7, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
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
208 changes: 121 additions & 87 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.19)

cmake_policy(VERSION 3.10...3.14)
cmake_policy(VERSION 3.19...3.23)

if(DEFINED ENV{SOURCE_DATE_EPOCH})
set(SOURCE_DATE_EPOCH "$ENV{SOURCE_DATE_EPOCH}")
Expand Down Expand Up @@ -104,11 +104,11 @@ if(DEFINED CMAKE_BUILD_TYPE AND "${CMAKE_BUILD_TYPE}" MATCHES "[Rr][Ee][Ll]")
if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fno-working-directory")
endif()
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fdebug-prefix-map=${CMAKE_SOURCE_DIR}=.")
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fdebug-prefix-map=\"${CMAKE_SOURCE_DIR}\"=.")
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-working-directory")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdebug-prefix-map=${CMAKE_SOURCE_DIR}=.")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdebug-prefix-map=\"${CMAKE_SOURCE_DIR}\"=.")
endif()

message( STATUS "Building OpenCoarrays version: ${full_git_describe}" )
Expand Down Expand Up @@ -139,6 +139,9 @@ endif()
if(NOT CMAKE_REQUIRED_FLAGS)
set(CMAKE_REQUIRED_FLAGS "")
endif()
if(NOT CMAKE_REQUIRED_DEFINITIONS)
set(CMAKE_REQUIRED_DEFINITIONS "")
endif()
if(NOT CMAKE_REQUIRED_LIBRARIES)
set(CMAKE_REQUIRED_LIBRARIES "")
endif()
Expand Down Expand Up @@ -204,6 +207,9 @@ endif()

if(CMAKE_BUILD_TYPE MATCHES "Debug|DEBUG|debug")
add_definitions(-DEXTRA_DEBUG_OUTPUT)
set(IMPI_BUILD debug)
else()
set(IMPI_BUILD release)
endif()

# We have populated CMAKE_Fortran_COMPILER_VERSION if it was missing
Expand Down Expand Up @@ -234,7 +240,7 @@ endif()

if(gfortran_compiler)
set(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS $<$<COMPILE_LANGUAGE:Fortran>:-fcoarray=single -ffree-form>)
set(CMAKE_REQUIRED_FLAGS -fcoarray=single)
endif()
include(CheckFortranSourceCompiles)
CHECK_Fortran_SOURCE_COMPILES("
Expand All @@ -243,7 +249,8 @@ CHECK_Fortran_SOURCE_COMPILES("
integer :: i
i = this_image()
end program
" Check_Simple_Coarray_Fortran_Source_Compiles)
" Check_Simple_Coarray_Fortran_Source_Compiles
SRC_EXT F90)
if(gfortran_compiler)
set (CMAKE_REQUIRED_FLAGS ${OLD_REQUIRED_FLAGS})
unset(OLD_REQUIRED_FLAGS)
Expand Down Expand Up @@ -273,102 +280,137 @@ if (C_COMPILER_NAME MATCHES "^[mM][pP][iI]")
set (MPI_C_COMPILER "${CMAKE_C_COMPILER}")
endif()

if(WIN32) # Only support building with GCC & GFortran using Intel MPI (OneAPI)
# Here we assume Intel ONEAPI and the environment is loaded
set( MPI_ASSUME_NO_BUILTIN_MPI TRUE )
set( MPI_CXX_SKIP_MPICXX TRUE )
cmake_path(SET MPI_ROOT NORMALIZE "$ENV{I_MPI_ROOT}")
set (IMPI_LIB_DIR "${MPI_ROOT}/lib/${IMPI_BUILD}")
set (IMPI_DLL_DIR "${MPI_ROOT}/bin/${IMPI_BUILD}")

find_library(IMPI_LIB
"impi.lib"
HINTS "${IMPI_LIB_DIR}"
DOC "Location of the Intel MPI impi.lib file"
REQUIRED
NO_DEFAULT_PATH)

find_file(IMPI_DLL
"impi.dll"
HINTS "${IMPI_DLL_DIR}"
DOC "Location of the Intel MPI impi.dll file"
REQUIRED
NO_DEFAULT_PATH)


set( MPI_C_LIBRARIES ${IMPI_LIB};${IMPI_DLL} CACHE FILEPATH "MPI C libs to link" )
set( MPI_C_LIB_NAMES impi CACHE FILEPATH "MPI lib names" )
set( MPI_Fortran_LIBRARIES ${IMPI_LIB};${IMPI_DLL} CACHE FILEPATH "MPI Fortran libs to link" )
set( MPI_Fortran_LIB_NAMES impi CACHE FILEPATH "MPI Fortran lib names" )
set( MPI_impi_LIBRARY ${IMPI_LIB} CACHE FILEPATH "MPI lib to link" )

set(MPI_Fortran_HAVE_F90_MODULE FALSE)
set(MPI_Fortran_HAVE_F08_MODULE FALSE)

endif()
find_package( MPI )

if ( (NOT MPI_C_FOUND) OR (NOT MPI_Fortran_FOUND) OR (NOT MPIEXEC))
if ( (NOT MPI_C_FOUND) OR (NOT MPI_Fortran_FOUND) OR (NOT MPIEXEC_EXECUTABLE))
# Get default install location of MPICH from install.sh
message(WARNING "Could not find all MPI components!")
message(WARNING "
MPI_C_FOUND = ${MPI_C_FOUND}
MPI_Fortran_FOUND = ${MPI_Fortran_FOUND}
MPIEXEC = ${MPIEXEC}
MPIEXEC_EXECUTABLE = ${MPIEXEC_EXECUTABLE}
")
execute_process( COMMAND "./install.sh" -P mpich
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE DEFAULT_MPICH_INSTALL_LOC
OUTPUT_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
OUTPUT_STRIP_TRAILING_WHITESPACE)
find_program (MY_MPI_EXEC NAMES mpirun mpiexec lamexec srun
PATHS "${DEFAULT_MPICH_INSTALL_LOC}" ENV PATH
HINTS "${FTN_COMPILER_DIR}" "${C_COMPILER_DIR}"
PATH_SUFFIXES bin)
set ( MPI_HOME "${MPI_HOME}" "${MY_MPI_EXEC}" "${MY_MPI_EXEC}/.." )
find_package( MPI REQUIRED )
endif()
list(REMOVE_DUPLICATES MPI_Fortran_INCLUDE_PATH)
list(REMOVE_DUPLICATES MPI_Fortran_INCLUDE_DIRS)

# Test for consistent MPI environment
if (NOT MPIEXEC)
# Test for consistent MPI environment but not on windows
if (NOT MPIEXEC_EXECUTABLE)
message ( ERROR "CMake failed to find `mpiexec` or similar. If building with `./install.sh` please
report this bug to the OpenCoarrays developers at
https://github.com/sourceryinstitute/opencoarrays/issues, otherwise point CMake
to the desired MPI runtime.")
else()
add_definitions(-DHAVE_MPI)
endif()

get_filename_component(MPIEXEC_RELATIVE_LOC "${MPIEXEC}"
PROGRAM)
get_filename_component(MPIEXEC_ABS_LOC "${MPIEXEC_RELATIVE_LOC}"
REALPATH)
get_filename_component(MPIEXEC_DIR "${MPIEXEC_ABS_LOC}"
DIRECTORY)

get_filename_component(MPICC_RELATIVE_LOC "${MPI_C_COMPILER}"
PROGRAM)
get_filename_component(MPICC_ABS_LOC "${MPICC_RELATIVE_LOC}"
REALPATH)
get_filename_component(MPICC_DIR "${MPICC_ABS_LOC}"
DIRECTORY)

get_filename_component(MPIFC_RELATIVE_LOC "${MPI_Fortran_COMPILER}"
PROGRAM)
get_filename_component(MPIFC_ABS_LOC "${MPIFC_RELATIVE_LOC}"
REALPATH)
get_filename_component(MPIFC_DIR "${MPIFC_ABS_LOC}"
DIRECTORY)

if ((MPIEXEC_DIR STREQUAL MPICC_DIR) AND (MPIEXEC_DIR STREQUAL MPIFC_DIR))
message ( STATUS "MPI runtime and compile time environments appear to be consistent")
else()
message ( WARNING "MPIEXEC is in \"${MPIEXEC_DIR},\"
if(NOT WIN32)
get_filename_component(MPIEXEC_RELATIVE_LOC "${MPIEXEC_EXECUTABLE}"
PROGRAM)
get_filename_component(MPIEXEC_ABS_LOC "${MPIEXEC_RELATIVE_LOC}"
REALPATH)
get_filename_component(MPIEXEC_DIR "${MPIEXEC_ABS_LOC}"
DIRECTORY)

get_filename_component(MPICC_RELATIVE_LOC "${MPI_C_COMPILER}"
PROGRAM)
get_filename_component(MPICC_ABS_LOC "${MPICC_RELATIVE_LOC}"
REALPATH)
get_filename_component(MPICC_DIR "${MPICC_ABS_LOC}"
DIRECTORY)

get_filename_component(MPIFC_RELATIVE_LOC "${MPI_Fortran_COMPILER}"
PROGRAM)
get_filename_component(MPIFC_ABS_LOC "${MPIFC_RELATIVE_LOC}"
REALPATH)
get_filename_component(MPIFC_DIR "${MPIFC_ABS_LOC}"
DIRECTORY)

if ((MPIEXEC_DIR STREQUAL MPICC_DIR) AND (MPIEXEC_DIR STREQUAL MPIFC_DIR))
message ( STATUS "MPI runtime and compile time environments appear to be consistent")
else()
message ( WARNING "MPIEXEC is in \"${MPIEXEC_DIR},\"
which differs from the location of MPICC and/or MPIFC which are in
\"${MPICC_DIR}\" and \"${MPIFC_DIR},\" respectively.
This is likely indicative of a problem. If building with `./install.sh` please report
this to the OpenCoarrays developers by filing a new issue at:
https://github.com/sourceryinstitute/OpenCoarrays/issues/new")
endif()
endif()

#-----------------------------------------------
# Work around bug #317 present on fedora systems
#-----------------------------------------------
if( (MPI_C_LINK_FLAGS MATCHES "noexecstack") OR (MPI_Fortran_LINK_FLAGS MATCHES "noexecstack") )
message ( WARNING
"The `noexecstack` linker flag was found in the MPI_<lang>_LINK_FLAGS variable. This is
#-----------------------------------------------
# Work around bug #317 present on fedora systems
#-----------------------------------------------
if( (MPI_C_LINK_FLAGS MATCHES "noexecstack") OR (MPI_Fortran_LINK_FLAGS MATCHES "noexecstack") )
message ( WARNING
"The `noexecstack` linker flag was found in the MPI_<lang>_LINK_FLAGS variable. This is
known to cause segmentation faults for some Fortran codes. See, e.g.,
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71729 or
https://github.com/sourceryinstitute/OpenCoarrays/issues/317.

`noexecstack` is being replaced with `execstack`"
)
string(REPLACE "noexecstack"
"execstack" MPI_C_LINK_FLAGS_FIXED ${MPI_C_LINK_FLAGS})
string(REPLACE "noexecstack"
"execstack" MPI_Fortran_LINK_FLAGS_FIXED ${MPI_Fortran_LINK_FLAGS})
set(MPI_C_LINK_FLAGS "${MPI_C_LINK_FLAGS_FIXED}" CACHE STRING
"MPI C linking flags" FORCE)
set(MPI_Fortran_LINK_FLAGS "${MPI_Fortran_LINK_FLAGS_FIXED}" CACHE STRING
"MPI Fortran linking flags" FORCE)
)
string(REPLACE "noexecstack"
"execstack" MPI_C_LINK_FLAGS_FIXED ${MPI_C_LINK_FLAGS})
string(REPLACE "noexecstack"
"execstack" MPI_Fortran_LINK_FLAGS_FIXED ${MPI_Fortran_LINK_FLAGS})
set(MPI_C_LINK_FLAGS "${MPI_C_LINK_FLAGS_FIXED}" CACHE STRING
"MPI C linking flags" FORCE)
set(MPI_Fortran_LINK_FLAGS "${MPI_Fortran_LINK_FLAGS_FIXED}" CACHE STRING
"MPI Fortran linking flags" FORCE)
endif()
endif()

#--------------------------------------------------------
# Make sure a simple "hello world" C mpi program compiles
#--------------------------------------------------------
set(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS ${MPI_C_COMPILE_FLAGS} ${MPI_C_LINK_FLAGS})
set(CMAKE_REQUIRED_FLAGS ${MPI_C_COMPILE_OPTIONS} ${MPI_C_LINK_FLAGS})
set(OLD_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
set(CMAKE_REQUIRED_DEFINITIONS ${MPI_C_COMPILE_DEFINITIONS})
set(OLD_INCLUDES ${CMAKE_REQUIRED_INCLUDES})
set(CMAKE_REQUIRED_INCLUDES ${MPI_C_INCLUDE_PATH})
set(CMAKE_REQUIRED_INCLUDES ${MPI_C_INCLUDE_DIRS})
set(OLD_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${MPI_C_LIBRARIES})
include (CheckCSourceCompiles)
Expand All @@ -390,6 +432,7 @@ int main(int argc, char** argv) {
}"
MPI_C_COMPILES)
set(CMAKE_REQUIRED_FLAGS ${OLD_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_DEFINITIONS ${OLD_REQUIRED_DEFINITIONS})
set(CMAKE_REQUIRED_INCLUDES ${OLD_INCLUDES})
set(CMAKE_REQUIRED_LIBRARIES ${OLD_LIBRARIES})
unset(OLD_REQUIRED_FLAGS)
Expand All @@ -409,9 +452,11 @@ endif()
# Try using mpi.mod first then fall back on includ 'mpif.h'
#--------------------------------------------------------------
set(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-ffree-form" ${MPI_Fortran_COMPILE_FLAGS} ${MPI_Fortran_LINK_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-ffree-form" ${MPI_Fortran_COMPILE_OPTIONS} ${MPI_Fortran_LINK_FLAGS})
set(OLD_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
set(CMAKE_REQUIRED_DEFINITIONS ${MPI_Fortran_COMPILE_DEFINITIONS})
set(OLD_INCLUDES ${CMAKE_REQUIRED_INCLUDES})
set(CMAKE_REQUIRED_INCLUDES ${MPI_Fortran_INCLUDE_PATH})
set(CMAKE_REQUIRED_INCLUDES ${MPI_Fortran_INCLUDE_DIRS})
set(OLD_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${MPI_Fortran_LIBRARIES})
include (CheckFortranSourceCompiles)
Expand All @@ -431,6 +476,7 @@ end program
"
MPI_Fortran_MODULE_COMPILES)
set(CMAKE_REQUIRED_FLAGS ${OLD_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_DEFINITIONS ${OLD_REQUIRED_DEFINITIONS})
set(CMAKE_REQUIRED_INCLUDES ${OLD_INCLUDES})
set(CMAKE_REQUIRED_LIBRARIES ${OLD_LIBRARIES})
unset(OLD_REQUIRED_FLAGS)
Expand All @@ -441,9 +487,11 @@ unset(OLD_LIBRARIES)
# If that failed try using mpif.h
#--------------------------------
set(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-ffree-form" ${MPI_Fortran_COMPILE_FLAGS} ${MPI_Fortran_LINK_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-ffree-form" ${MPI_Fortran_COMPILE_OPTIONS} ${MPI_Fortran_LINK_FLAGS})
set(OLD_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
set(CMAKE_REQUIRED_DEFINITIONS ${MPI_Fortra_COMPILE_DEFINITIONS})
set(OLD_INCLUDES ${CMAKE_REQUIRED_INCLUDES})
set(CMAKE_REQUIRED_INCLUDES ${MPI_Fortran_INCLUDE_PATH})
set(CMAKE_REQUIRED_INCLUDES ${MPI_Fortran_INCLUDE_DIRS})
set(OLD_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${MPI_Fortran_LIBRARIES})
include (CheckFortranSourceCompiles)
Expand All @@ -463,6 +511,7 @@ end program
"
MPI_Fortran_INCLUDE_COMPILES)
set(CMAKE_REQUIRED_FLAGS ${OLD_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_DEFINITIONS ${OLD_REQUIRED_DEFINITIONS})
set(CMAKE_REQUIRED_INCLUDES ${OLD_INCLUDES})
set(CMAKE_REQUIRED_LIBRARIES ${OLD_LIBRARIES})
unset(OLD_REQUIRED_FLAGS)
Expand All @@ -487,26 +536,6 @@ else()
)
endif()

#----------------
# Setup MPI flags
#----------------
if(NOT CMAKE_C_COMPILE_FLAGS)
set(CMAKE_C_COMPILE_FLAGS "")
endif()
if(NOT CMAKE_C_LINK_FLAGS)
set(CMAKE_C_LINK_FLAGS "")
endif()
if(NOT CMAKE_Fortran_COMPILE_FLAGS)
set(CMAKE_Fortran_COMPILE_FLAGS "")
endif()
if(NOT CMAKE_Fortran_LINK_FLAGS)
set(CMAKE_Fortran_LINK_FLAGS "")
endif()
set(CMAKE_C_COMPILE_FLAGS "${CMAKE_C_COMPILE_FLAGS} ${MPI_C_COMPILE_FLAGS}")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} ${MPI_C_LINK_FLAGS}")
set(CMAKE_Fortran_COMPILE_FLAGS "${CMAKE_Fortran_COMPILE_FLAGS} ${MPI_Fortran_COMPILE_FLAGS}")
set(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS} ${MPI_Fortran_LINK_FLAGS}")

#---------------------------------------------------
# Use standardized GNU install directory conventions
#---------------------------------------------------
Expand All @@ -531,9 +560,13 @@ if(APPLE)
find_program(CODESIGN codesign)
endif()

# We need bash, even on windows, for now at least. A light version like Git-Bash works best,
# WSL dumps you into your home directory and there's nothing you can do about it.
find_program(BASH_EXECUTABLE bash
REQUIRED)
function(caf_compile_executable target main_depend)
set(includes "")
foreach(includedir ${MPI_Fortran_INCLUDE_PATH})
foreach(includedir ${MPI_Fortran_INCLUDE_DIRS})
list(APPEND includes "-I${includedir}")
endforeach()
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
Expand All @@ -544,7 +577,7 @@ function(caf_compile_executable target main_depend)
list(APPEND localDefs "-D${d}")
endforeach()
add_custom_command(OUTPUT "${target}"
COMMAND "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/caf"
COMMAND "${BASH_EXECUTABLE}" "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/caf"
${includes} ${localDefs} ${config_Fortran_flags}
-o "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${target}"
"${CMAKE_CURRENT_SOURCE_DIR}/${main_depend}"
Expand Down Expand Up @@ -588,10 +621,11 @@ endfunction()
#-----------------------------------------------

find_program(style_pl style.pl "${CMAKE_SOURCE_DIR}/developer-scripts/")
find_package(Perl)
function(check_script_style script_full_path)
if(style_pl)
if(style_pl AND PERL_FOUND)
add_test(NAME "style:${script_full_path}"
COMMAND "${style_pl}" "${script_full_path}")
COMMAND "${PERL_EXECUTABLE}" "${style_pl}" "${script_full_path}")
endif()
endfunction()

Expand Down Expand Up @@ -703,9 +737,9 @@ function(add_caf_test name num_caf_img test_target)
endif()
set(test_parameters -np ${num_caf_img} ${test_parameters})
if(DEFINED ARGN)
add_test(NAME ${name} COMMAND "bash" "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/cafrun" ${test_parameters} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test_target}" ${ARGN})
add_test(NAME ${name} COMMAND "${BASH_EXECUTABLE}" "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/cafrun" ${test_parameters} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test_target}" ${ARGN})
else()
add_test(NAME ${name} COMMAND "bash" "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/cafrun" ${test_parameters} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test_target}")
add_test(NAME ${name} COMMAND "${BASH_EXECUTABLE}" "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/cafrun" ${test_parameters} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test_target}")
endif()
set_property(TEST ${name} PROPERTY PASS_REGULAR_EXPRESSION "Test passed.")
endfunction(add_caf_test)
Expand Down
Loading