1 #***********************************************************************
2 #* GNU Lesser General Public License
4 #* This file is part of the GFDL Flexible Modeling System (FMS).
6 #* FMS is free software: you can redistribute it and/or modify it under
7 #* the terms of the GNU Lesser General Public License as published by
8 #* the Free Software Foundation, either version 3 of the License, or (at
9 #* your option) any later version.
11 #* FMS is distributed in the hope that it will be useful, but WITHOUT
12 #* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 #* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #* You should have received a copy of the GNU Lesser General Public
17 #* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 #***********************************************************************
20 # Copyright (c) GFDL, @underwoo
22 cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
24 # add build type for debug, overrides default flags (set with $FCFLAGS, $CFLAGS)
25 set(CMAKE_Fortran_FLAGS_DEBUG)
27 # Define the CMake project
30 DESCRIPTION "GFDL FMS Library"
31 HOMEPAGE_URL "https://www.gfdl.noaa.gov/fms"
34 include(GNUInstallDirs)
36 if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)$")
37 message(STATUS "Setting build type to 'Release' as none was specified.")
40 CACHE STRING "Choose the type of build." FORCE)
41 set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
44 if(NOT CMAKE_C_COMPILER_ID MATCHES "^(Intel|GNU|Clang|IntelLLVM)$")
46 WARNING "Compiler not officially supported: ${CMAKE_C_COMPILER_ID}")
49 if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "^(Intel|GNU|IntelLLVM)$")
51 WARNING "Compiler not officially supported: ${CMAKE_Fortran_COMPILER_ID}")
54 # Append directory that contains CMake Modules for building FMS
55 list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
58 option(OPENMP "Build FMS with OpenMP support" OFF)
59 option(32BIT "Build 32-bit (r4) FMS library" ON)
60 option(64BIT "Build 64-bit (r8) FMS library" OFF)
61 option(FPIC "Build with position independent code" OFF)
63 # Options for compiler definitions
64 option(INTERNAL_FILE_NML "Enable compiler definition -DINTERNAL_FILE_NML" ON)
65 option(ENABLE_QUAD_PRECISION "Enable compiler definition -DENABLE_QUAD_PRECISION" ON)
66 option(GFS_PHYS "Enable compiler definition -DGFS_PHYS" OFF)
67 option(LARGEFILE "Enable compiler definition -Duse_LARGEFILE" OFF)
68 option(WITH_YAML "Enable compiler definition -Duse_yaml" OFF)
69 option(USE_DEPRECATED_IO "Enable compiler definition -Duse_deprecated_io (compile with fms_io/mpp_io)" OFF)
72 list(APPEND kinds "r4")
75 list(APPEND kinds "r8")
78 message(STATUS "Single Precision 32BIT: ${32BIT}")
79 message(STATUS "Double Precision 64BIT: ${64BIT}")
80 message(FATAL_ERROR "Either 32BIT or 64BIT should be ON")
84 find_package(MPI REQUIRED COMPONENTS C Fortran)
85 find_package(NetCDF REQUIRED COMPONENTS C Fortran)
87 # Check for the OpenMP library and set the required compile flags
89 find_package(OpenMP REQUIRED COMPONENTS C Fortran)
93 find_package(libyaml REQUIRED)
94 include_directories(${LIBYAML_INCLUDE_DIR})
97 # Enables position independent code (i.e., -fPIC)
99 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
102 # Collect FMS Fortran source files
103 list(APPEND fms_fortran_src_files
104 affinity/fms_affinity.F90
105 amip_interp/amip_interp.F90
106 astronomy/astronomy.F90
107 axis_utils/axis_utils.F90
108 axis_utils/axis_utils2.F90
109 block_control/block_control.F90
110 column_diagnostics/column_diagnostics.F90
111 constants/constants.F90
112 constants/fmsconstants.F90
113 constants4/constantsr4.F90
114 constants4/fmsconstantsr4.F90
115 coupler/atmos_ocean_fluxes.F90
116 coupler/coupler_types.F90
117 coupler/ensemble_manager.F90
118 data_override/get_grid_version.F90
119 data_override/data_override.F90
120 diag_integral/diag_integral.F90
121 diag_manager/diag_axis.F90
122 diag_manager/diag_data.F90
123 diag_manager/diag_grid.F90
124 diag_manager/diag_manager.F90
125 diag_manager/diag_output.F90
126 diag_manager/diag_table.F90
127 diag_manager/diag_util.F90
128 diag_manager/fms_diag_time_reduction.F90
129 diag_manager/fms_diag_outfield.F90
130 diag_manager/fms_diag_elem_weight_procs.F90
131 diag_manager/fms_diag_fieldbuff_update.F90
132 diag_manager/fms_diag_bbox.F90
133 diag_manager/fms_diag_time_utils.F90
134 diag_manager/fms_diag_object.F90
135 diag_manager/fms_diag_yaml.F90
136 diag_manager/fms_diag_file_object.F90
137 diag_manager/fms_diag_field_object.F90
138 diag_manager/fms_diag_axis_object.F90
139 diag_manager/fms_diag_dlinked_list.F90
140 diag_manager/fms_diag_object_container.F90
141 diag_manager/fms_diag_buffer.F90
142 diag_manager/fms_diag_output_buffer.F90
143 diag_manager/fms_diag_time_reduction.F90
144 diag_manager/fms_diag_outfield.F90
145 diag_manager/fms_diag_elem_weight_procs.F90
146 diag_manager/fms_diag_fieldbuff_update.F90
147 diag_manager/fms_diag_bbox.F90
148 drifters/cloud_interpolator.F90
149 drifters/drifters.F90
150 drifters/drifters_comm.F90
151 drifters/drifters_core.F90
152 drifters/drifters_input.F90
153 drifters/drifters_io.F90
154 drifters/quicksort.F90
155 exchange/stock_constants.F90
157 field_manager/field_manager.F90
158 field_manager/fm_util.F90
159 field_manager/fm_yaml.F90
162 fms2_io/blackboxio.F90
163 fms2_io/fms_io_utils.F90
164 fms2_io/fms_netcdf_domain_io.F90
165 fms2_io/fms_netcdf_unstructured_domain_io.F90
167 fms2_io/netcdf_io.F90
168 horiz_interp/horiz_interp_bicubic.F90
169 horiz_interp/horiz_interp_bilinear.F90
170 horiz_interp/horiz_interp_conserve.F90
171 horiz_interp/horiz_interp_spherical.F90
172 horiz_interp/horiz_interp_type.F90
173 horiz_interp/horiz_interp.F90
174 interpolator/interpolator.F90
175 memutils/memutils.F90
176 monin_obukhov/monin_obukhov_inter.F90
177 monin_obukhov/monin_obukhov.F90
189 mpp/mpp_parameter.F90
190 mpp/mpp_utilities.F90
191 parser/yaml_parser.F90
192 parser/fms_yaml_output.F90
193 platform/platform.F90
194 random_numbers/mersennetwister.F90
195 random_numbers/random_numbers.F90
196 sat_vapor_pres/sat_vapor_pres_k.F90
197 sat_vapor_pres/sat_vapor_pres.F90
198 string_utils/fms_string_utils.F90
199 time_interp/time_interp_external.F90
200 time_interp/time_interp_external2.F90
201 time_interp/time_interp.F90
202 time_manager/get_cal_time.F90
203 time_manager/time_manager.F90
204 topography/gaussian_topog.F90
205 topography/topography.F90
206 tracer_manager/tracer_manager.F90
207 tridiagonal/tridiagonal.F90
211 # Collect FMS C source files
212 list(APPEND fms_c_src_files
215 mosaic/create_xgrid.c
216 mosaic/gradient_c2l.c
221 parser/yaml_parser_binding.c
222 parser/yaml_output_functions.c
223 string_utils/fms_string_utils_binding.c
226 # Collect FMS header files
227 list(APPEND fms_header_files
228 include/file_version.h
229 include/fms_platform.h
232 # Standard FMS compiler definitions
238 include(CheckFunctionExists)
239 check_function_exists(gettid HAVE_GETTID)
241 list(APPEND fms_defs HAVE_GETTID)
244 # Additional (optional) compiler definitions
248 if(CONSTANTS STREQUAL "GFS")
249 list(APPEND fms_defs GFS_CONSTANTS)
250 elseif(CONSTANTS STREQUAL "GEOS")
251 list(APPEND fms_defs GEOS_CONSTANTS)
252 elseif(CONSTANTS STREQUAL "GFDL")
253 list(APPEND fms_defs GFDL_CONSTANTS)
255 message(FATAL_ERROR "CONSTANTS=${CONSTANTS} option not supported")
259 list(APPEND fms_defs GFS_PHYS)
263 list(APPEND fms_defs use_yaml)
266 if(USE_DEPRECATED_IO)
267 list(APPEND fms_defs use_deprecated_io)
270 if(INTERNAL_FILE_NML)
271 list(APPEND fms_defs INTERNAL_FILE_NML)
274 if(ENABLE_QUAD_PRECISION)
275 list(APPEND fms_defs ENABLE_QUAD_PRECISION)
279 list(APPEND fms_defs use_LARGEFILE)
282 # Precision-based compiler definitions
284 list(APPEND r4_defs OVERLOAD_R4 OVERLOAD_R8)
287 # Add platform specific compiler definitions
289 list(APPEND fms_defs __APPLE__)
292 # Obtain compiler-specific flags
293 include(fms_compiler_flags)
295 foreach(kind ${kinds})
297 set(libTgt fms_${kind})
298 set(includeDir "include_${kind}")
299 set(moduleDir "${CMAKE_CURRENT_BINARY_DIR}/${includeDir}")
302 add_library(${libTgt}_c OBJECT ${fms_c_src_files})
304 target_include_directories(${libTgt}_c PRIVATE include)
305 target_compile_definitions(${libTgt}_c PRIVATE "${fms_defs}")
307 target_link_libraries(${libTgt}_c PRIVATE NetCDF::NetCDF_C
311 target_link_libraries(${libTgt}_c PRIVATE OpenMP::OpenMP_C)
315 add_library(${libTgt}_f OBJECT ${fms_fortran_src_files})
317 target_include_directories(${libTgt}_f PRIVATE include
323 column_diagnostics/include
324 monin_obukhov/include
325 sat_vapor_pres/include
327 diag_integral/include
328 random_numbers/include
336 field_manager/include
338 tracer_manager/include
342 data_override/include
345 target_compile_definitions(${libTgt}_f PRIVATE "${fms_defs}")
346 target_compile_definitions(${libTgt}_f PRIVATE "${${kind}_defs}")
348 string(TOLOWER ${CMAKE_BUILD_TYPE} build_type)
349 if (NOT build_type STREQUAL debug)
350 set_target_properties(${libTgt}_f PROPERTIES COMPILE_FLAGS
353 set_target_properties(${libTgt}_f PROPERTIES Fortran_MODULE_DIRECTORY
356 target_link_libraries(${libTgt}_f PRIVATE NetCDF::NetCDF_Fortran
359 if(OpenMP_Fortran_FOUND)
360 target_link_libraries(${libTgt}_f PRIVATE OpenMP::OpenMP_Fortran)
363 # Check if gnu 10 or higher
364 # this should only be needed with mpich, but wasn't able to find a good way to find the MPI flavor consistently
365 if ( CMAKE_Fortran_COMPILER_VERSION MATCHES "1[0-9]\.[0-9]*\.[0-9]*" AND CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
366 include(CheckFortranCompilerFlag)
367 check_fortran_compiler_flag("-fallow-argument-mismatch" _arg_mismatch_flag)
368 if(_arg_mismatch_flag)
369 message(STATUS "Adding -fallow-argument-mismatch flag to compile with GCC >=10 and MPICH")
370 target_compile_options(${libTgt}_f PRIVATE "-fallow-argument-mismatch;-w")
375 add_library(${libTgt} STATIC $<TARGET_OBJECTS:${libTgt}_c>
376 $<TARGET_OBJECTS:${libTgt}_f>)
378 target_include_directories(${libTgt} PUBLIC
379 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
380 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/fms>
381 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/fms/include>
382 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/fms2_io/include>
383 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/column_diagnostics/include>
384 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/astronomy/include>
385 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/monin_obukhov/include>
386 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/sat_vapor_pres/include>
387 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/field_manager/include>
388 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/horiz_interp/include>
389 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/mosaic2/include>
390 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/string_utils/include>
391 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/mpp/include>
392 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/diag_manager/include>
393 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/topography/include>
394 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/random_numbers/include>
395 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/diag_integral/include>
396 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/diag_manager/include>
397 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tracer_manager/include>
398 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/interpolator/include>
399 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/coupler/include>
400 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/mosaic2/include>
401 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/data_override/include>
402 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tridiagonal/include>
403 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/amip_interp/include>)
405 target_include_directories(${libTgt} INTERFACE
406 $<BUILD_INTERFACE:${moduleDir}>
407 $<INSTALL_INTERFACE:${includeDir}>)
409 target_compile_definitions(${libTgt} PRIVATE "${fms_defs}")
410 target_compile_definitions(${libTgt} PRIVATE "${${kind}_defs}")
412 target_link_libraries(${libTgt} PUBLIC NetCDF::NetCDF_Fortran
415 if(OpenMP_Fortran_FOUND)
416 target_link_libraries(${libTgt} PRIVATE OpenMP::OpenMP_C OpenMP::OpenMP_Fortran)
419 add_library(FMS::${libTgt} ALIAS ${libTgt})
421 list(APPEND LIB_TARGETS ${libTgt})
422 install(DIRECTORY ${moduleDir} DESTINATION ${CMAKE_INSTALL_PREFIX})
423 install(FILES ${fms_header_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/${includeDir})
428 TARGETS ${LIB_TARGETS}
430 RUNTIME DESTINATION bin
431 LIBRARY DESTINATION lib
432 ARCHIVE DESTINATION lib)
435 include(CMakePackageConfigHelpers)
436 set(CONFIG_INSTALL_DESTINATION lib/cmake/fms)
438 export(EXPORT FMSExports
440 FILE fms-targets.cmake)
442 configure_package_config_file(
443 ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FMSConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/fms-config.cmake
444 INSTALL_DESTINATION ${CONFIG_INSTALL_DESTINATION})
445 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fms-config.cmake
446 DESTINATION ${CONFIG_INSTALL_DESTINATION})
448 write_basic_package_version_file(
449 ${CMAKE_CURRENT_BINARY_DIR}/fms-config-version.cmake
450 VERSION ${PROJECT_VERSION}
451 COMPATIBILITY AnyNewerVersion)
452 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fms-config-version.cmake
453 DESTINATION ${CONFIG_INSTALL_DESTINATION})
455 install(EXPORT FMSExports
457 FILE fms-targets.cmake
458 DESTINATION ${CONFIG_INSTALL_DESTINATION})