cmake_minimum_required(VERSION 3.10) project(PIOF LANGUAGES Fortran) include(CheckFunctionExists) include(ExternalProject) include(LibCheck) #============================================================================== # DEFINE THE TARGET #============================================================================== set(PIO_Fortran_SRCS pio_nf.F90 pio.F90 pio_kinds.F90 pio_types.F90 piolib_mod.F90 pio_support.F90) set(PIO_GenF90_SRCS pionfatt_mod.F90 pionfput_mod.F90 pionfget_mod.F90 piodarray.F90) set(PIO_Fortran_MODS ${CMAKE_CURRENT_BINARY_DIR}/pio.mod ${CMAKE_CURRENT_BINARY_DIR}/pio_nf.mod ${CMAKE_CURRENT_BINARY_DIR}/pio_types.mod ${CMAKE_CURRENT_BINARY_DIR}/piolib_mod.mod ${CMAKE_CURRENT_BINARY_DIR}/pionfget_mod.mod ${CMAKE_CURRENT_BINARY_DIR}/pio_kinds.mod ${CMAKE_CURRENT_BINARY_DIR}/pio_support.mod ${CMAKE_CURRENT_BINARY_DIR}/piodarray.mod ${CMAKE_CURRENT_BINARY_DIR}/pionfatt_mod.mod ${CMAKE_CURRENT_BINARY_DIR}/pionfput_mod.mod) if(NETCDF_INTEGRATION) set(PIO_Fortran_SRCS ${PIO_Fortran_SRCS} ncint_mod.F90) set(PIO_Fortran_MODS ${PIO_Fortran_MODS} ${CMAKE_CURRENT_BINARY_DIR}/ncint_mod.mod) endif() set(CMAKE_POSITION_INDEPENDENT_CODE ON) add_library(piof ${PIO_Fortran_SRCS} ${PIO_GenF90_SRCS}) # Always use -fPIC set_property(TARGET piof PROPERTY POSITION_INDEPENDENT_CODE ON) if(NOT PIO_ENABLE_FORTRAN) set_target_properties(piof PROPERTIES EXCLUDE_FROM_ALL TRUE) endif() # Include flib source and binary directories (for Fortran modules) target_include_directories(piof PUBLIC $ PUBLIC $ PUBLIC $) # System and compiler CPP directives target_compile_definitions(piof PUBLIC ${CMAKE_SYSTEM_DIRECTIVE}) target_compile_definitions(piof PUBLIC ${CMAKE_Fortran_COMPILER_DIRECTIVE}) # Compiler-specific compile options if("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "GNU") target_compile_options(piof PRIVATE -ffree-line-length-none) elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "NAG") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -mismatch_all ") # target_compile_options(piof PRIVATE -mismatch_all) elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Cray") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ef") elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -debug minimal") endif() if(CMAKE_BUILD_TYPE STREQUAL "DEBUG") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -g") endif() # Look for c_sizeof capability check_macro (Fortran_CSIZEOF NAME TryCSizeOf.f90 HINTS ${CMAKE_MODULE_PATH} COMMENT "whether Fortran compiler supports c_sizeof") if(NOT Fortran_CSIZEOF) target_compile_definitions(piof PUBLIC NO_C_SIZEOF) endif() # Look for filesystem hints if(PIO_FILESYSTEM_HINTS) if(PIO_FILESYSTEM_HINTS STREQUAL lustre) message(STATUS "PIO will use lustre filesystem hints") target_compile_definitions(piof PUBLIC PIO_LUSTRE_HINTS) elseif(PIO_FILESYSTEM_HINTS STREQUAL gpfs) message(STATUS "PIO will use gpfs filesystem hints") target_compile_definitions(piof PUBLIC PIO_GPFS_HINTS) else() message(WARNING "${PIO_FILESYSTEM_HINTS} not valid option for PIO_FILESYSTEM_HINTS; use gpfs or lustre.") endif() endif() #============================================================================== # DEFINE THE INSTALL #============================================================================== set_target_properties(piof PROPERTIES EXPORT_NAME PIO_Fortran) # Library install(TARGETS piof EXPORT PIOFortranTargets DESTINATION lib INCLUDES DESTINATION include) # Fortran Modules install(FILES ${PIO_Fortran_MODS} DESTINATION include) install(EXPORT PIOFortranTargets FILE PIOFortranTargets.cmake NAMESPACE PIO:: DESTINATION lib/cmake/PIO) #============================================================================== # DEFINE THE DEPENDENCIES #============================================================================== #===== pioc ===== target_link_libraries(piof PUBLIC pioc) #===== genf90 ===== if(DEFINED GENF90_PATH) add_custom_target(genf90 DEPENDS ${GENF90_PATH}/genf90.pl) else() ExternalProject_Add(genf90 PREFIX ${CMAKE_CURRENT_BINARY_DIR}/genf90 GIT_REPOSITORY https://github.com/PARALLELIO/genf90 GIT_TAG genf90_200608 UPDATE_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "") ExternalProject_Get_Property(genf90 SOURCE_DIR) set(GENF90_PATH ${SOURCE_DIR}) unset(SOURCE_DIR) endif() add_dependencies(piof genf90) #===== Fortran Source Generation with GenF90 ===== foreach(SRC_FILE IN LISTS PIO_GenF90_SRCS) add_custom_command(OUTPUT ${SRC_FILE} COMMAND ${GENF90_PATH}/genf90.pl ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FILE}.in > ${SRC_FILE} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FILE}.in genf90) endforeach() #===== MPI ===== if(PIO_USE_MPISERIAL) if(MPISERIAL_Fortran_FOUND) target_compile_definitions(piof PRIVATE _MPISERIAL) target_include_directories(piof PUBLIC ${MPISERIAL_Fortran_INCLUDE_DIRS}) target_link_libraries(piof PUBLIC ${MPISERIAL_Fortran_LIBRARIES}) set(WITH_PNETCDF FALSE) set(MPI_Fortran_INCLUDE_PATH ${MPISERIAL_Fortran_INCLUDE_DIRS}) endif() endif() # Check MPI I/O capabilities find_path(MPIF_H_PATH NAMES mpif.h PATHS ${MPI_Fortran_INCLUDE_PATH} NO_DEFAULT_PATH) if(MPIF_H_PATH) check_macro(MPI_HAS_MPIIO NAME TryMPIIO.f90 HINTS ${CMAKE_MODULE_PATH} DEFINITIONS -I${MPIF_H_PATH} COMMENT "whether MPIIO is supported") if(${MPI_HAS_MPIIO}) message(STATUS "MPIIO verified and enabled.") target_compile_definitions(piof PUBLIC USEMPIIO) else() message(STATUS "MPIIO failed verification and therefore disabled.") endif() else() message(STATUS "MPIIO not detected and therefore disabled.") endif() # Check for MPI Fortran module find_path(MPIMOD_PATH NAMES mpi.mod MPI.mod HINTS ${MPI_Fortran_INCLUDE_PATH}) check_macro(MPI_HAS_Fortran_MOD NAME TryMPIMod.f90 HINTS ${CMAKE_MODULE_PATH} DEFINITIONS -I${MPIMOD_PATH} COMMENT "whether MPI Fortran module is supported") if(${MPI_HAS_Fortran_MOD}) message(STATUS "MPI Fortran module verified and enabled.") else() message(STATUS "MPI Fortran module failed verification and therefore disabled.") if(PIO_ENABLE_TIMING AND NOT GPTL_Fortran_Perf_FOUND) target_compile_definitions(gptl PUBLIC NO_MPIMOD) endif() target_compile_definitions(piof PUBLIC NO_MPIMOD) endif() #===== GPTL ===== if(PIO_ENABLE_TIMING) if(GPTL_Fortran_Perf_FOUND) message(STATUS "Found GPTL Fortran Perf: ${GPTL_Fortran_Perf_LIBRARIES}") target_include_directories(piof PUBLIC ${GPTL_Fortran_INCLUDE_DIRS}) target_link_libraries(piof PUBLIC ${GPTL_Fortran_LIBRARIES}) else() message(STATUS "Using internal GPTL Fortran library for timing") target_link_libraries(piof PUBLIC gptl) endif() endif() #===== NetCDF-Fortran ===== if(NetCDF_Fortran_FOUND) # Use NetCDF-Fortran include directories and libraries target_include_directories(piof PUBLIC ${NetCDF_Fortran_INCLUDE_DIRS}) target_link_libraries(piof PUBLIC ${NetCDF_Fortran_LIBRARIES}) endif() #===== PnetCDF ===== if(PnetCDF_Fortran_FOUND) target_include_directories(piof PUBLIC ${PnetCDF_Fortran_INCLUDE_DIRS}) target_link_libraries(piof PUBLIC ${PnetCDF_Fortran_LIBRARIES}) # Check library for varn functions set(CMAKE_REQUIRED_LIBRARIES ${PnetCDF_Fortran_LIBRARY}) endif() #===== Add EXTRAs ===== target_include_directories(piof PUBLIC $) target_link_libraries(piof PUBLIC ${PIO_Fortran_EXTRA_LIBRARIES}) target_compile_options(piof PRIVATE ${PIO_Fortran_EXTRA_COMPILE_OPTIONS}) target_compile_definitions(piof PUBLIC ${PIO_Fortran_EXTRA_COMPILE_DEFINITIONS}) if(PIO_Fortran_EXTRA_LINK_FLAGS) set_target_properties(piof PROPERTIES LINK_FLAGS ${PIO_Fortran_EXTRA_LINK_FLAGS}) endif() #===== Check for necessities ===== if(NOT PnetCDF_Fortran_FOUND AND NOT NetCDF_Fortran_FOUND) message(FATAL_ERROR "Must have PnetCDF and/or NetCDF Fortran libraries") endif() set(FFLAGS ${CMAKE_Fortran_FLAGS} PARENT_SCOPE) get_target_property(fppdefs piof COMPILE_DEFINITIONS) get_target_property(fincludes piof INCLUDE_DIRECTORIES) foreach(x IN LISTS fppdefs) string(APPEND FPPFLAGS " -D${x}") endforeach() foreach(x IN LISTS fincludes) if(x) string(APPEND FPPFLAGS " -I${x}") endif() endforeach() set(FPPFLAGS ${FPPFLAGS} PARENT_SCOPE)