# git $Id$ # svn $Id: CMakeLists.txt 1201 2023-09-25 18:28:39Z arango $ #:::::::::::::::::::::::::::::::::::::::::::::::::::::: David Robertson ::: # Copyright (c) 2002-2023 The ROMS/TOMS Group ::: # Licensed under a MIT/X style license ::: # See License_ROMS.md ::: #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # # Top-Level CMake File Definitions. cmake_minimum_required( VERSION 3.13.0 FATAL_ERROR ) list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Compilers) Message( STATUS "module path = ${CMAKE_MODULE_PATH}" ) set( CMAKE_DIRECTORY_LABELS ${PROJECT_NAME} ) find_package( Git ) if( GIT_FOUND ) if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git ) message( STATUS "Getting and setting GIT_URL and GIT_REV" ) execute_process( COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GITURL OUTPUT_STRIP_TRAILING_WHITESPACE ) execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --verify HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GITREV OUTPUT_STRIP_TRAILING_WHITESPACE ) add_compile_definitions( GIT_URL="${GITURL}" GIT_REV="${GITREV}" SVN_URL="https://www.myroms.org/svn/src" ) endif() endif() find_package( Subversion ) if( SUBVERSION_FOUND ) if( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.svn ) message( STATUS "Getting and setting SVN_URL and SVN_REV" ) Subversion_WC_INFO(${CMAKE_CURRENT_SOURCE_DIR} roms IGNORE_SVN_FAILURE) add_compile_definitions( SVN_URL="${roms_WC_URL}" SVN_REV="${roms_WC_REVISION}" ) endif() endif() # Figure out if we are using ecbuild. if( DEFINED ENV{ECBUILD_MODULE_PATH} ) set( IN_ECBUILD TRUE ) endif() project(roms VERSION 4.1 LANGUAGES Fortran) if( IN_ECBUILD ) set( ECBUILD_DEFAULT_BUILD_TYPE Release ) set( ENABLE_OS_TESTS OFF CACHE BOOL "Disable OS tests" FORCE ) set( ENABLE_LARGE_FILE_SUPPORT OFF CACHE BOOL "Disable testing of large file support" FORCE ) set( ENABLE_MPI ON CACHE BOOL "Compile with MPI" ) find_package(ecbuild 3.3.2 REQUIRED) include( ecbuild_system NO_POLICY_SCOPE ) ecbuild_declare_project() ecbuild_enable_fortran( REQUIRED ) endif() # Include ROMS cmake files. include( roms_functions ) include( roms_compiler_flags ) include( roms_config ) # Set MYDEFS to list of Compiling definition to check for options that require # cmake configuration adjustments get_directory_property( MYDEFS COMPILE_DEFINITIONS ) # Check if we need to include ESMF if( MYDEFS MATCHES "ESMF_LIB" ) if( NOT ESMF_FOUND ) find_package( ESMF REQUIRED ) if( ESMF_FOUND ) message( STATUS "ESMF_INCLUDE_DIRECTORIES = ${ESMF_INCLUDE_DIRECTORIES}" ) message( STATUS "ESMF_LIBRARY_LOCATION = ${ESMF_LIBRARY_LOCATION}" ) message( STATUS "ESMF_INTERFACE_LINK_LIBRARIES = ${ESMF_INTERFACE_LINK_LIBRARIES}" ) include_directories( ${ESMF_INCLUDE_DIRECTORIES} ) else() message( FATAL "ESMF NOT FOUND" ) endif() endif() endif() ########################################################################### # Project ########################################################################### set( ROMS_LINKER_LANGUAGE Fortran ) if( NOT IN_ECBUILD ) # Set Fortran modules directory when not using ecbuild. It is set # automatically when using ecbuild. set( CMAKE_Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/modules" ) set( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE ) set( CMAKE_SKIP_BUILD_RPATH FALSE ) # MacOS requires an extra parameter for rpath to work properly. This is # set automatically when using ecbuild. if( APPLE ) set( CMAKE_MACOSX_RPATH ON ) set( CMAKE_INSTALL_RPATH @loader_path/../lib ) else() set( CMAKE_INSTALL_RPATH \$ORIGIN/../lib ) endif() endif() ########################################################################### # Dependencies ########################################################################### # NetCDF Library. if(DEFINED ENV{SINGULARITY_COMMAND} AND IN_ECBUILD ) find_package( NetCDF REQUIRED COMPONENTS Fortran ) include_directories( ${NETCDF_INCLUDE_DIRS} ) list( APPEND netcdf_libs "netcdff" "netcdf" ) else() # Find NetCDF outside singularity. "target_link_libraries" is found below # because it has to be defined after "add_executable". The link_netcdf() # function can be found in Compilers/roms_functions.cmake. link_netcdf() include_directories( ${netcdf_idir} ) link_directories( ${netcdf_ldirs} ) endif() # SCORPIO Include directories if( SCORPIO ) include_directories( ${PIO_INCDIR} ) message( STATUS "SCORPIO included: ${PIO_INCDIR}" ) endif() ########################################################################### # ROMS ########################################################################### add_subdirectory( "Master" ) add_subdirectory( "ROMS/Drivers" ) add_subdirectory( "ROMS/Functionals" ) add_subdirectory( "ROMS/Modules" ) add_subdirectory( "ROMS/Nonlinear" ) add_subdirectory( "ROMS/Nonlinear/BBL" ) add_subdirectory( "ROMS/Nonlinear/Biology" ) add_subdirectory( "ROMS/Nonlinear/Sediment" ) add_subdirectory( "ROMS/Utility" ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} "/usr/local/include" "$ENV{NETCDF}/include" "Master" "ROMS/Drivers" "ROMS/Functionals" "ROMS/Include" "ROMS/Modules" "ROMS/Nonlinear" "ROMS/Nonlinear/BBL" "ROMS/Nonlinear/Biology" "ROMS/Nonlinear/Sediment" "ROMS/Utility" ) link_directories( ${CMAKE_CURRENT_BINARY_DIR} "/usr/local/lib" "$ENV{NETCDF}/lib" ) list(APPEND srcs ${Master_files} ${ROMS_Drivers_files} ${ROMS_Functionals_files} ${ROMS_Modules_files} ${ROMS_Nonlinear_files} ${ROMS_Nonlinear_BBL_files} ${ROMS_Nonlinear_Biology_files} ${ROMS_Nonlinear_Sediment_files} ${ROMS_Utility_files} ) if( ADJOINT ) add_subdirectory( "ROMS/Adjoint" ) add_subdirectory( "ROMS/Adjoint/Biology" ) include_directories( "ROMS/Adjoint" "ROMS/Adjoint/Biology" ) list( APPEND srcs ${ROMS_Adjoint_files} ${ROMS_Adjoint_Biology_files} ) # Free format flags for certain files that may exceed 132 characters per line set_property( SOURCE ${CMAKE_CURRENT_BINARY_DIR}/f90/ad_biology.f90 APPEND_STRING PROPERTY COMPILE_FLAGS ${ROMS_FREEFLAGS} ) endif() if( REPRESENTER ) add_subdirectory( "ROMS/Representer" ) add_subdirectory( "ROMS/Representer/Biology" ) include_directories( "ROMS/Representer" "ROMS/Representer/Biology" ) list( APPEND srcs ${ROMS_Representer_files} ${ROMS_Representer_Biology_files} ) # Free format flags for certain files that may exceed 132 characters per line set_property( SOURCE ${CMAKE_CURRENT_BINARY_DIR}/f90/rp_biology.f90 APPEND_STRING PROPERTY COMPILE_FLAGS ${ROMS_FREEFLAGS} ) endif() if( TANGENT ) add_subdirectory( "ROMS/Tangent" ) add_subdirectory( "ROMS/Tangent/Biology" ) include_directories( "ROMS/Tangent" "ROMS/Tangent/Biology" ) list( APPEND srcs ${ROMS_Tangent_files} ${ROMS_Tangent_Biology_files} ) # Free format flags for certain files that may exceed 132 characters per line set_property( SOURCE ${CMAKE_CURRENT_BINARY_DIR}/f90/tl_biology.f90 APPEND_STRING PROPERTY COMPILE_FLAGS ${ROMS_FREEFLAGS} ) endif() #-------------------------------------------------------------------------- # ROMS specific rules. #-------------------------------------------------------------------------- # Special CPP definitions for "mod_strings.F". set_property( SOURCE ROMS/Modules/mod_strings.F APPEND_STRING PROPERTY COMPILE_DEFINITIONS MY_OS='${my_os}' MY_CPU='${my_cpu}' MY_FORT='${my_fort}' MY_FC='${my_fc}' MY_FFLAGS='${my_fflags}' ) # Free format flags for certain files that may exceed 132 characters per line set_property( SOURCE ${CMAKE_CURRENT_BINARY_DIR}/f90/mod_ncparam.f90 ${CMAKE_CURRENT_BINARY_DIR}/f90/mod_strings.f90 ${CMAKE_CURRENT_BINARY_DIR}/f90/analytical.f90 ${CMAKE_CURRENT_BINARY_DIR}/f90/biology.f90 APPEND_STRING PROPERTY COMPILE_FLAGS ${ROMS_FREEFLAGS} ) ########################################################################### # Clean-up the dependencies ########################################################################### # Remove the .F files from "DependInfo.cmake" for the Objects target. If # the "Objects" target changes names this MUST be updated. add_custom_command( OUTPUT fixdep COMMAND ${PERL} ${CMAKE_CURRENT_SOURCE_DIR}/ROMS/Bin/FixDependInfo.pl ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Objects.dir/DependInfo.cmake VERBATIM ) # Custom target needed to make the custom command above run add_custom_target(fix ALL DEPENDS fixdep ) # The "preprocess_fortran" function tells CMake how to create .f90 files. # It allows CMake crippled Fortran depency tracker to look for the right # modules using the pre-processed .f90 files instead of the .F files. # # The dependency generator is easily confused by CPP if-directives. # This also allows us to feed .f90 files to CMake as the sources to all # the ROMS code and eliminate compiler assumptions related to .F files. # # The function "preprocess_fortran" is defined in the "roms_functions.cmake" # file in the "Compilers" directory. preprocess_fortran( ${srcs} ) set( All_f90s "${f90srcs}" ) # Adding all the sources as an OBJECT library prevents CMake from trying # to link an executable or collect the object files into a library. # # The libXXX.(a|so) libraries will be created below. add_library( Objects OBJECT ${All_f90s} ) if( IN_ECBUILD ) ecbuild_add_library( TARGET ${PROJECT_NAME} SOURCES $<TARGET_OBJECTS:Objects> PUBLIC_INCLUDES INSTALL_HEADERS LISTED LINKER_LANGUAGE ${ROMS_LINKER_LANGUAGE} ) endif() # Add dependency on custom target "fix" so "DependInfo.cmake" is cleaned up # before the the dependencies are calculated. add_dependencies( Objects fix ) # This is to set the install prefix to the build directory as long as the # user has not set their own install prefix. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH "..." FORCE) endif() # Shared libraries need PIC. There is perfomance degradation to position # independent code so we only set this if shared libraries are requested. # This really has no effect when using ecbuild since Position Indpendent # Code (PIC) is enabled by default inside ecbuild regardless of the type # of library requested. set( deplib ) if( IN_ECBUILD ) message( STATUS "Enabling position independent code" ) set_property(TARGET Objects PROPERTY POSITION_INDEPENDENT_CODE 1) else() if( LIBSHARED ) message( STATUS "Enabling position independent code" ) set_property(TARGET Objects PROPERTY POSITION_INDEPENDENT_CODE 1) add_library( ROMS_shared SHARED $<TARGET_OBJECTS:Objects> ) set_target_properties(ROMS_shared PROPERTIES OUTPUT_NAME ROMS) install( TARGETS ROMS_shared LIBRARY ) # This is needed to add to the depency list of the ROMS executable # since it is linking with libROMS.so instead of libROMS_shared.so # The executable doesn't see "ROMS" as a target generated by this # project so it starts linking before the library is fully assembled. list( APPEND deplib ROMS_shared ) endif() if( LIBSTATIC ) add_library( ROMS_static STATIC $<TARGET_OBJECTS:Objects> ) set_target_properties(ROMS_static PROPERTIES OUTPUT_NAME ROMS) install( TARGETS ROMS_static ARCHIVE ) # This is needed to add to the depency list of the ROMS executable # since it is linking with libROMS.a instead of libROMS_static.a # The executable doesn't see "ROMS" as a target generated by this # project so it starts linking before the library is fully assembled. list( APPEND deplib ROMS_static ) endif() # There needs to be at least one source file for the "add_executable" line # so "Master/master.F" is removed from "Master/CMakeLists.txt" and added # manually here. # # I would have done all the files in "Master" here to simplify things # but "roms_kernel.F", "coupler.F", and "propagator.F" include # modules needed in other parts of the code outside "Master". if( ROMS_EXECUTABLE ) set( CMAKE_BUILD_WITH_INSTALL_RPATH FALSE ) message( STATUS "CMAKE_INSTALL_RPATH_USE_LINK_PATH = ${CMAKE_INSTALL_RPATH_USE_LINK_PATH}" ) message( STATUS "CMAKE_SKIP_BUILD_RPATH = ${CMAKE_SKIP_BUILD_RPATH}" ) message( STATUS "CMAKE_BUILD_WITH_INSTALL_RPATH = ${CMAKE_BUILD_WITH_INSTALL_RPATH}" ) message( STATUS "CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}" ) if( APPLE ) message( STATUS "CMAKE_MACOSX_RPATH = ${CMAKE_MACOSX_RPATH}" ) endif() # If PARPACK/ARPACK is needed add directory for the linker. The # "link_directories" and "target_link_libraries" for PARPACK/ARPACK # are separated because "link_libraries" has to be set before # "add_executable" and "target_link_libraries" has to be set after. if( ARPACK ) link_directories( ${PARPACK_LIBDIR} ${ARPACK_LIBDIR} ) endif() # If parallel I/O using SCORPIO is requested, add directory for the # linker. The "link_directories" and "target_link_libraries" for # are separated because "link_libraries" has to be set before # "add_executable" and "target_link_libraries" has to be set after. if( SCORPIO ) link_directories( ${PNETCDF_LIBDIR} ${PIO_LIBDIR} ) endif() preprocess_fortran( Master/master.F ) set( master_f90 "${f90srcs}" ) add_executable( "${BIN}" ${master_f90} ) add_dependencies( "${BIN}" Objects ${deplib} ) if( LIBSHARED AND LIBSTATIC ) Message( STATUS "Both LIBSHARED and LIBSTATIC are enabled, the linker will probably default to the shared ROMS library." ) target_link_libraries( "${BIN}" ROMS ${netcdf_libs} ) elseif( LIBSHARED ) Message( STATUS "Linking ROMS using shared ROMS library." ) target_link_libraries( "${BIN}" ROMS ${netcdf_libs} ) elseif( LIBSTATIC ) Message( STATUS "Linking ROMS using static ROMS library." ) target_link_libraries( "${BIN}" ROMS ${netcdf_libs} ) else() Message( FATAL_ERROR "Unknown configuration!" ) endif() # If ARPACK is needed, add to linking library list. # The path to the library is set above. if( ARPACK ) target_link_libraries( "${BIN}" parpack arpack ) endif() # if ESMF is requested, add to linking library list if( MYDEFS MATCHES "ESMF_LIB" ) target_link_libraries( "${BIN}" ESMF ) endif() # If parallel I/O with SCORPIO is requested, add to linking library list. # The path to the libraries are set above. if( SCORPIO ) target_link_libraries( "${BIN}" pnetcdf piof pioc ) endif() install( TARGETS "${BIN}" RUNTIME ) endif() endif() if( IN_ECBUILD ) message( STATUS "CMAKE_Fortran_MODULE_DIRECTORY=${CMAKE_Fortran_MODULE_DIRECTORY}" ) message( STATUS "CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}" ) target_include_directories( ${PROJECT_NAME} INTERFACE $<BUILD_INTERFACE:${CMAKE_Fortran_MODULE_DIRECTORY}> $<INSTALL_INTERFACE:${CMAKE_Fortran_MODULE_DIRECTORY}> ) ecbuild_install_project( NAME ${PROJECT_NAME} ) ecbuild_print_summary() endif() file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/fortran_flags ${my_fflags} )