Merge branch 'release-v4.6.0' of github.com:wrf-model/WRF
[WRF.git] / CMakeLists.txt
blobd1a1297f2f995e1b0f3b20cf720da7888b01dc1c
1 cmake_minimum_required( VERSION 3.20 )
2 cmake_policy( SET CMP0118 NEW )
4 enable_language( C )
5 enable_language( CXX )
6 enable_language( Fortran )
8 project( WRF )
9 set( EXPORT_NAME ${PROJECT_NAME} )
11 if ( DEFINED CMAKE_TOOLCHAIN_FILE )
12   set( WRF_CONFIG ${CMAKE_TOOLCHAIN_FILE} )
13   # message( STATUS "Loading configuration file... : ${WRF_CONFIG}" )
14   # include( ${WRF_CONFIG} )
15 endif()
17 # list( APPEND CMAKE_MODULE_PATH         )
18 list( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/ ${PROJECT_SOURCE_DIR}/cmake/modules )
20 # Use link paths as rpaths
21 set( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE )
22 set( CMAKE_Fortran_PREPROCESS          ON )
24 # This is always set
25 list( APPEND CMAKE_C_PREPROCESSOR_FLAGS -P -nostdinc -traditional )
27 include( CMakePackageConfigHelpers )
28 include( CheckIPOSupported )
29 include( c_preproc   )
30 include( m4_preproc  )
31 include( target_copy )
32 include( confcheck   )
33 include( gitinfo     )
34 include( printOption )
35 include( wrf_case_setup )
36 include( wrf_get_version )
38 check_ipo_supported( RESULT IPO_SUPPORT )
40 # First grab git info
41 wrf_git_commit(
42                 RESULT_VAR        GIT_VERSION
43                 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
44                 )
46 # Configure file for usage
47 configure_file(
48                 ${PROJECT_SOURCE_DIR}/cmake/template/commit_decl.cmake
49                 ${PROJECT_BINARY_DIR}/inc/commit_decl
50                 @ONLY
51                 )
53 # Grab version info
54 wrf_get_version( ${PROJECT_SOURCE_DIR}/README )
56 ################################################################################
58 ## Options that can be user configured
60 ################################################################################
61 # Mode configuration
63 set( OPTIMIZATION_LEVEL "" )
64 set( WRF_OS             "" )
65 set( WRF_MACH           "" )
67 if ( "${CMAKE_BUILD_TYPE}" STREQUAL "" )
68   set( CMAKE_BUILD_TYPE Release )
69   message( STATUS "Set default build type to ${CMAKE_BUILD_TYPE}" )
70 endif()
71 ################################################################################
72 ## WRF Core selection
73 ################################################################################
74 set( WRF_CORE_OPTIONS
75       # Options listed here
76       ARW
77       CONVERT # This exists in compile but not configure
78       DA      # Var directory
79       DA_4D_VAR
80       PLUS
81       )
83 set( WRF_CORE "" CACHE STRING "WRF_CORE" )
84 if ( "${WRF_CORE}" STREQUAL "" )
85   # Set default WRF_CORE
86   list( GET WRF_CORE_OPTIONS 0 WRF_CORE )
87 endif()
89 ################################################################################
90 ## WRF Nesting selection
91 ################################################################################
92 set( WRF_NESTING_OPTIONS
93       # Options listed here
94       NONE
95       BASIC
96       MOVES
97       VORTEX
98       )
100 set( WRF_NESTING "" CACHE STRING "WRF_NESTING" )
101 if ( "${WRF_NESTING}" STREQUAL "" )
102   # Set default WRF_NESTING
103   list( GET WRF_NESTING_OPTIONS 0 WRF_NESTING )
104 endif()
106 ################################################################################
107 ## WRF Case selection
108 ##!TODO Maybe one day make it so this doesn't need to be a selection and all are
109 ##      always built?
110 ################################################################################
111 set( WRF_CASE_OPTIONS
112       # Options listed here
113       EM_REAL # make this the default
114       # EM_IDEAL # Technically doable but does anyone build this? It is not a target option in make
115       EM_FIRE
116       EM_SCM_XY
117       EM_TROPICAL_CYCLONE
118       EM_HELDSUAREZ
120       # These are sub-categories of ideal - Keep these lower in the list
121       EM_B_WAVE # Keep this one here as it is used to check index
122       EM_GRAV2D_X
123       EM_HILL2D_X
124       EM_LES
125       EM_QUARTER_SS
126       EM_SEABREEZE2D_X
127       EM_CONVRAD
128       EM_SQUALL2D_X
129       EM_SQUALL2D_Y
130       )
132 set( WRF_CASE "" CACHE STRING "WRF_CASE" )
133 if ( "${WRF_CASE}" STREQUAL "" )
134   # Set default WRF_CASE
135   list( GET WRF_CASE_OPTIONS 0 WRF_CASE )
136 endif()
138 # DO NOT USE OPTION - IT DOES NOT WORK AS ANTICIPATED EVEN WHEN CLEARING CACHE - YOU HAVE BEEN WARNED
139 # If you add anything here, the description should be the name itself - this helps the configuration script
140 set( USE_DOUBLE  OFF CACHE BOOL "USE_DOUBLE"  )
141 set( USE_MPI     OFF CACHE BOOL "USE_MPI"     )
142 set( USE_OPENMP  OFF CACHE BOOL "USE_OPENMP"  )
143 set( USE_HDF5    OFF CACHE BOOL "USE_HDF5"    )
144 set( USE_JASPER  OFF CACHE BOOL "USE_JASPER"  )
145 set( USE_PIO     OFF CACHE BOOL "USE_PIO"     )
146 set( USE_IPO     OFF CACHE BOOL "USE_IPO"     )
149 set( ENABLE_CHEM       OFF CACHE BOOL "ENABLE_CHEM"      )
150 set( ENABLE_CMAQ       OFF CACHE BOOL "ENABLE_CMAQ"      )
151 set( ENABLE_CTSM       OFF CACHE BOOL "ENABLE_CTSM"      )
152 set( ENABLE_DFI_RADAR  OFF CACHE BOOL "ENABLE_DFI_RADAR" )
153 set( ENABLE_HYDRO      OFF CACHE BOOL "ENABLE_HYDRO"     )
154 set( ENABLE_KPP        OFF CACHE BOOL "ENABLE_KPP"       )
155 set( ENABLE_MARS       OFF CACHE BOOL "ENABLE_MARS"      )
156 set( ENABLE_TERRAIN    OFF CACHE BOOL "ENABLE_TERRAIN"   )
157 set( ENABLE_TITAN      OFF CACHE BOOL "ENABLE_TITAN"     )
158 set( ENABLE_VENUS      OFF CACHE BOOL "ENABLE_VENUS"     )
160 # What do these defines even do if they are always on????
161 set( USE_ALLOCATABLES     ON CACHE BOOL "USE_ALLOCATABLES"    )
162 set( wrfmodel             ON CACHE BOOL "wrfmodel"            )
163 set( GRIB1                ON CACHE BOOL "GRIB1"               )
164 set( INTIO                ON CACHE BOOL "INTIO"               )
165 set( KEEP_INT_AROUND      ON CACHE BOOL "KEEP_INT_AROUND"     )
166 set( LIMIT_ARGS           ON CACHE BOOL "LIMIT_ARGS"          )
168 # Toggles, how do we want to best address these options? Environment vars are not
169 # the best
170 set( WRFIO_NCD_NO_LARGE_FILE_SUPPORT  OFF CACHE BOOL "WRFIO_NCD_NO_LARGE_FILE_SUPPORT" )
171 set( FORCE_NETCDF_CLASSIC OFF CACHE BOOL "FORCE_NETCDF_CLASSIC" )
172 set( BUILD_RRTMG_FAST     OFF CACHE BOOL "BUILD_RRTMG_FAST"     )
173 set( BUILD_RRTMK          OFF CACHE BOOL "BUILD_RRTMK"          )
174 set( BUILD_SBM_FAST        ON CACHE BOOL "BUILD_SBM_FAST"       )
175 set( SHOW_ALL_VARS_USED   OFF CACHE BOOL "SHOW_ALL_VARS_USED"   )
178 # TODO investigate if this needs set
179 # Not cached, cannot be changed, do not touch
180 set( USE_M4               ON )
181 # Same thing -what do these defines even do if they are always on????
182 set( NMM_CORE            OFF )
183 set( NETCDF               ON )
186 # Special internal flag for profiling compilation
187 set( PROFILE_COMPILATION  OFF CACHE BOOL "PROFILE_COMPILATION" )
190 # From arch/preamble
191 #### Single location for defining total number of domains.  You need
192 #### at least 1 + 2*(number of total nests).  For example, 1 coarse
193 #### grid + three fine grids = 1 + 2(3) = 7, so MAX_DOMAINS=7.
194 set( MAX_DOMAINS_F 21 )
197 #### DM buffer length for the configuration flags.
199 set( CONFIG_BUF_LEN 65536 )
201 #### Size of bitmasks (in 4byte integers) of stream masks for WRF I/O
203 set( MAX_HISTORY    25    )
205 set( IWORDSIZE      4     )
206 set( DWORDSIZE      8     )
207 set( LWORDSIZE      4     )
210 ########################
212 ################################################################################
214 ## Load options selected and any ancillary logic
216 ################################################################################
218 # Check WRF options
219 if ( NOT ${WRF_CORE} IN_LIST WRF_CORE_OPTIONS )
220   message( FATAL_ERROR "WRF Core option not recognized : ${WRF_CORE}" )
221 endif()
223 if ( NOT ${WRF_NESTING} IN_LIST WRF_NESTING_OPTIONS )
224   message( FATAL_ERROR "WRF Nesting option not recognized : ${WRF_NESTING}" )
225 endif()
227 if ( NOT ${WRF_CASE} IN_LIST WRF_CASE_OPTIONS )
228   message( FATAL_ERROR "WRF Case option not recognized : ${WRF_CASE}" )
229 endif()
231 # Handle selection
232 set( EM_CORE 1 )
233 # Far easier to write this one as normal logic rather than generator expression
234 if( ${WRF_CORE} STREQUAL "CONVERT" OR ${WRF_CORE} STREQUAL "COAMPS" )
235   set( EM_CORE 0 )
236 endif()
238 set( MOVE_NESTS 0 )
239 # Far easier to write this one as normal logic rather than generator expression
240 if( ${WRF_NESTING} STREQUAL "MOVES" OR ${WRF_NESTING} STREQUAL "VORTEX" )
241   set( MOVE_NESTS 1 )
242 endif()
244 if ( ${ENABLE_KPP} AND NOT ${ENABLE_CHEM} )
245   message( WARNING "ENABLE_KPP requires ENABLE_CHEM but is not set, ignoring" )
246 endif()
249 # Additional information on the type of case we are compiling
250 string( TOLOWER ${WRF_CASE} WRF_CASE_FOLDER )
251 string( REPLACE "em_" "" WRF_CASE_MODULE ${WRF_CASE_FOLDER} )
253 # Find if it is a specialized ideal case or general
254 list( FIND WRF_CASE_OPTIONS EM_B_WAVE   START_GENERAL_IDEAL_CASE_IDX )
255 list( FIND WRF_CASE_OPTIONS ${WRF_CASE} CURRENT_CASE_IDX )
256 set( WRF_GENERAL_IDEAL_CASE TRUE )
257 if ( ${CURRENT_CASE_IDX} LESS ${START_GENERAL_IDEAL_CASE_IDX} )
258   set( WRF_GENERAL_IDEAL_CASE FALSE )
259 endif()
261 if ( NOT ${WRFIO_NCD_NO_LARGE_FILE_SUPPORT} )
262   message( STATUS "netCDF large file support not suppressed, if available it will be used" )
263 endif()
265 # Hydro option requires MPI
266 if ( ${ENABLE_HYDRO} AND NOT ${USE_MPI} )
267   message( STATUS "WRF Hydro requires MPI usage" )
268   set( USE_MPI ON CACHE BOOL "Required by configuration" FORCE )
269 endif()
271 # Handle double promotion - doing this here instead of from config.cmake toolchain
272 # file since the double promotion logic is a nightmare
273 list( FIND WRF_CORE_OPTIONS ${WRF_CORE} CURRENT_WRF_CORE_IDX )
274 list( FIND WRF_CORE_OPTIONS "DA"        START_DA_IDX )
275 # DA + WRF PLUS cores require double precision
276 if ( ${CURRENT_WRF_CORE_IDX} GREATER_EQUAL ${START_DA_IDX} AND NOT ${USE_DOUBLE} )
277   # if ( # Apparently set regardless of compiler
278   #     ${CMAKE_Fortran_COMPILER_ID} STREQUAL "GNU" OR
279   #     ${CMAKE_Fortran_COMPILER_ID} STREQUAL "Fujitsu" )
280   message( STATUS "DA and PLUS Core builds require double precision" )
281   set( USE_DOUBLE ON CACHE BOOL "Required by configuration" FORCE )
282   # endif()
283 endif()
285 if ( ${USE_DOUBLE} )
286   set( RWORDSIZE    8     )
287   if ( ${BUILD_SBM_FAST} )
288     set( BUILD_SBM_FAST OFF CACHE BOOL "Required by configuration" FORCE )
289     message( STATUS "BUILD_SBM_FAST does not support double, turning off" )
290   endif()
291 else()
292   set( RWORDSIZE    4     )
293 endif()
295 math( EXPR RWORDSIZE_B "8 * ${RWORDSIZE}" )
298 # Check if IPO usage
299 if ( ${USE_IPO} )
300   if ( NOT ${IPO_SUPPORT} )
301     message( STATUS "IPO/LTO not supported, request ignored" )
302     set( USE_IPO OFF CACHE BOOL "Required by configuration" FORCE )
303   endif()
304 endif()
306 ################################################################################
308 ## Now find packages that cross-compilation is potentially handled
310 ################################################################################
311 # If nesting is enabled, DM_PARALLEL must be set, but if this is a non-MPI compilation
312 # we must stub its usage
313 list( FIND WRF_NESTING_OPTIONS ${WRF_NESTING} CURRENT_NESTING_IDX )
315 # If MPI or nesting
316 set( USE_RSL_LITE OFF )
317 if ( ${USE_MPI} )
318   # Through ***MUCH*** debugging, if utilizing MPI_<LANG>_COMPILER
319   # https://cmake.org/cmake/help/latest/module/FindMPI.html#variables-for-locating-mpi
320   # the find logic makes a mess of things by utilizing <mpi> -show[me]
321   # Which may or may not get polluted by the environment
322   # It still technically finds MPI but the output is nonintuitive
323   # saying things like hdf5 or pthread
324   find_package( MPI REQUIRED COMPONENTS Fortran C )
325   add_compile_definitions(
326                           USE_MPI=1
327                           DM_PARALLEL
328                           )
330   if ( DEFINED WRF_MPI_Fortran_FLAGS AND NOT "${WRF_MPI_Fortran_FLAGS}" STREQUAL "" )
331     add_compile_options(
332                         $<$<COMPILE_LANGUAGE:Fortran>:${WRF_MPI_Fortran_FLAGS}>
333                         )
334   endif()
336   if ( DEFINED WRF_MPI_C_FLAGS AND NOT "${WRF_MPI_C_FLAGS}" STREQUAL "" )
337     add_compile_options(
338                         $<$<COMPILE_LANGUAGE:C>:${WRF_MPI_C_FLAGS}>
339                         )
340   endif()
342   # Check if MPI in all its glory has forced IPO down our throats due to hard-coding the wrapper flags
343   # https://www.open-mpi.org/faq/?category=mpi-apps#why-no-rpath LOL!
344   # Quote "The default installation of Open MPI tries very hard to not include any non-essential flags in the wrapper compilers"
345   # Okay, yea sure. Maybe it's the distro's lib config that does add all the bloatware flags
346   if ( NOT ${USE_IPO} )
347     # get compile info
348     message( STATUS "Checking if MPI requires IPO" )
349     foreach( IPO_FLAG IN LISTS CMAKE_Fortran_COMPILE_OPTIONS_IPO )
350       string( FIND "${MPI_Fortran_COMPILE_OPTIONS}" ${IPO_FLAG} MPI_FORCE_IPO )
351       # Note we are not using IN_LIST since certain IPO settings might not exactly match (e.g.  -flto vs -flto=auto)
352       if ( NOT ${MPI_FORCE_IPO} EQUAL -1 )
353         # An IPO flag was found
354         if ( ${IPO_SUPPORT} )
355           message( STATUS "NOTE: ${MPI_Fortran_COMPILER} requires IPO flags be enabled, forcing USE_IPO=ON" )
356           set( USE_IPO ON CACHE BOOL "Required by MPI" FORCE )
357           break()
358         else()
359           message( FATAL_ERROR "${MPI_Fortran_COMPILER} requires IPO support but selected compiler does not support it, would fail to link" )
360         endif()
361       endif()
362     endforeach()
363   endif()
365   set( USE_RSL_LITE ON )
366 # We know NONE is the zero index so compare against that
367 elseif( ${CURRENT_NESTING_IDX} GREATER 0 )
368   add_compile_definitions(
369                           DM_PARALLEL
370                           STUBMPI
371                           )
372   set( USE_RSL_LITE ON )
373 endif()
375 if ( ${USE_OPENMP} )
376   find_package( OpenMP REQUIRED COMPONENTS Fortran C )
377   add_compile_definitions( USE_OPENMP=1 SM_PARALLEL )
378 endif()
380 if ( ${USE_M4} )
381   find_program(
382                 M4_PROGRAM
383                 m4
384                 REQUIRED
385                 )
386   set( M4_FLAGS ${WRF_M4_FLAGS} -Uinclude -Uindex -Ulen )
387 endif()
391 # HDF5 has some funky weirdness between versions where the casing has changed
392 # Optional
393 if ( ${USE_HDF5} )
394   find_package( HDF5 )
395 endif()
397 # Optional for grib2
398 if ( ${USE_JASPER} )
399   find_package( Jasper 1.900.1...<1.900.24 )
400 endif()
402 # Optional
403 if ( ${USE_PIO} )
404   find_package( PIO QUIET )
405 endif()
407 if ( ${ENABLE_TERRAIN} )
408   find_package( RPC )
409 endif()
411 if ( ${ENABLE_CTSM} )
412   # Will need our own finder
413   # find_package( CTSM REQUIRED )
414 endif()
416 # Will need our own finder
417 # find_package( GPFS   REQUIRED )
419 # Included is a lightweight finder, but we really should switch to using UniData's netCDF cmake config
420 # The reason these are two separate and not COMPONENTS of one larger package is because that is the way UniData
421 # has laid out the cmake configs for each respective package
422 find_package( netCDF         REQUIRED )
423 find_package( netCDF-Fortran REQUIRED )
425 # Make use of version checking here and not in find_package for previous versions that did not use cmake
426 if ( ( NOT netCDF_VERSION GREATER_EQUAL "4.1.3" ) OR ( NOT netCDF-Fortran_VERSION GREATER_EQUAL "4.1.3" ) )
427   message( FATAL "Please make sure NETCDF versions are 4.1.3 or later. " )
428 endif()
430 find_package( pnetCDF QUIET )
432 # Attempt to find zlib packaged with netcdf first
433 set( ZLIB_ROOT ${netCDF_PREFIX} )
434 find_package( ZLIB   REQUIRED )
435 find_package( CURL   REQUIRED )
437 ################################################################################
439 ## Print out final set of options to be used
440 ## DO NOT MODIFY OPTIONS BEYOND THIS POINT
442 ################################################################################
444 if ( DEFINED CMAKE_TOOLCHAIN_FILE )
445   print_option( WRF_CONFIG         20 ${BOLD_CYAN} )
446 endif()
448 print_option( CMAKE_BUILD_TYPE 20 ${BOLD_CYAN} )
451 print_option( WRF_CORE         20 ${BOLD_CYAN} )
452 print_option( WRF_NESTING      20 ${BOLD_CYAN} )
453 print_option( WRF_CASE         20 ${BOLD_CYAN} )
456 print_option( USE_DOUBLE       20 )
457 print_option( USE_MPI          20 )
458 print_option( USE_OPENMP       20 )
459 print_option( USE_IPO          20 )
461 print_option( ENABLE_CHEM      20 )
462 print_option( ENABLE_CLM       20 )
463 print_option( ENABLE_CMAQ      20 )
464 print_option( ENABLE_DFI_RADAR 20 )
465 print_option( ENABLE_HYDRO     20 )
466 print_option( ENABLE_KPP       20 )
467 print_option( ENABLE_MARS      20 )
468 print_option( ENABLE_TERRAIN   20 )
469 print_option( ENABLE_TITAN     20 )
470 print_option( ENABLE_VENUS     20 )
472 print_option( USE_ALLOCATABLES 20 )
473 print_option( wrfmodel         20 )
474 print_option( GRIB1            20 )
475 print_option( INTIO            20 )
476 print_option( KEEP_INT_AROUND  20 )
477 print_option( LIMIT_ARGS       20 )
479 print_option( FORCE_NETCDF_CLASSIC 20 )
480 print_option( BUILD_RRTMG_FAST     20 )
481 print_option( BUILD_RRTMK          20 )
482 print_option( BUILD_SBM_FAST       20 )
483 print_option( SHOW_ALL_VARS_USED   20 )
485 print_option( WRFIO_NCD_NO_LARGE_FILE_SUPPORT 36 )
487 ################################################################################
489 ## Set any global cmake options decided by particular configuration
491 ################################################################################
492 set( CMAKE_INTERPROCEDURAL_OPTIMIZATION ${USE_IPO} )
494 ################################################################################
496 ## Configuration checks for features & intrinsices
498 ################################################################################
499 add_subdirectory( confcheck )
501 ################################################################################
503 ## Adjust flags based on compiler and linker used
505 ################################################################################
507 # https://stackoverflow.com/a/47927921
508 # Define compile options to be inherited for directories
509 define_property(
510                 SOURCE
511                 PROPERTY   COMPILE_FLAGS
512                 INHERITED
513                 BRIEF_DOCS "brief-doc"
514                 FULL_DOCS  "full-doc"
515                 )
517 define_property(
518                 DIRECTORY
519                 PROPERTY   COMPILE_FLAGS
520                 INHERITED
521                 BRIEF_DOCS "brief-doc"
522                 FULL_DOCS  "full-doc"
523                 )
525 # Get current build type flags and put them in there
526 if ( "${CMAKE_BUILD_TYPE}" STREQUAL "Release" )
527   set_directory_properties(
528                             PROPERTIES
529                               COMPILE_FLAGS
530                               $<$<COMPILE_LANGUAGE:Fortran>:${WRF_FCOPTIM}>
531                             )
532 # else()
533 #   # Assume no optimization
534 #   set_directory_properties(
535 #                             PROPERTIES
536 #                               COMPILE_FLAGS
537 #                               $<$<COMPILE_LANGUAGE:Fortran>:${WRF_FCNOOPT}>
538 #                             )
539 endif()
542 # This is really ugly but such is the cost of supporting many ways to say the same thing
543 # https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
544 add_compile_options(
545                     # Use "" and ; specifically to evaluate correctly
546                     # "$<$<COMPILE_LANG_AND_ID:Fortran,Absoft>:>"                                 #@ Absoft Fortran
547                     # "$<$<COMPILE_LANG_AND_ID:Fortran,ADSP>:>"                                   #@ Analog VisualDSP++
548                     # "$<$<COMPILE_LANG_AND_ID:Fortran,AppleClang>:>"                             #@ Apple Clang
549                     # "$<$<COMPILE_LANG_AND_ID:Fortran,ARMCC>:>"                                  #@ ARM Compiler
550                     # "$<$<COMPILE_LANG_AND_ID:Fortran,ARMClang>:>"                               #@ ARM Compiler based on Clang
551                     # "$<$<COMPILE_LANG_AND_ID:Fortran,Bruce>:>"                                  #@ Bruce C Compiler
552                     # "$<$<COMPILE_LANG_AND_ID:Fortran,CCur>:>"                                   #@ Concurrent Fortran
553                     # "$<$<COMPILE_LANG_AND_ID:Fortran,Clang>:>"                                  #@ LLVM Clang
554                     "$<$<COMPILE_LANG_AND_ID:Fortran,Cray>:-s;integer32;-s;real${RWORDSIZE_B}>" #@ Cray Compiler
555                     # "$<$<COMPILE_LANG_AND_ID:Fortran,Embarcadero>:>"                            #@ Embarcadero
556                     "$<$<AND:$<BOOL:${USE_DOUBLE}>,$<COMPILE_LANG_AND_ID:Fortran,Flang>>:-fdefault-real-${RWORDSIZE}>"                  #@ Classic Flang Fortran Compiler
557                     # "$<$<COMPILE_LANG_AND_ID:Fortran,LLVMFlang>:>"                              #@ LLVM Flang Fortran Compiler
558                     "$<$<COMPILE_LANG_AND_ID:Fortran,Fujitsu>:-CcdRR${RWORDSIZE}>"              #@ Fujitsu HPC compiler (Trad mode)
559                     # "$<$<COMPILE_LANG_AND_ID:Fortran,FujitsuClang>:>"                           #@ Fujitsu HPC compiler (Clang mode)
560                     "$<$<COMPILE_LANG_AND_ID:Fortran,G95>:-r${RWORDSIZE};-i4>"                                    #@ G95 Fortran
561                     "$<$<AND:$<BOOL:${USE_DOUBLE}>,$<COMPILE_LANG_AND_ID:Fortran,GNU>>:-fdefault-real-${RWORDSIZE}>"         #@ GNU Compiler Collection
562                     # "$<$<COMPILE_LANG_AND_ID:Fortran,GHS>:>"                                    #@ Green Hills Software
563                     # "$<$<COMPILE_LANG_AND_ID:Fortran,HP>:>"                                     #@ Hewlett-Packard Compiler
564                     # "$<$<COMPILE_LANG_AND_ID:Fortran,IAR>:>"                                    #@ IAR Systems
565                     "$<$<COMPILE_LANG_AND_ID:Fortran,Intel>:-real-size;${RWORDSIZE_B};-i4>"     #@ Intel Classic Compiler
566                     "$<$<COMPILE_LANG_AND_ID:Fortran,IntelLLVM>:-real-size;${RWORDSIZE_B};-i4>" #@ Intel LLVM-Based Compiler
567                     # "$<$<COMPILE_LANG_AND_ID:Fortran,LCC>:>"                                    #@ MCST Elbrus C/C++/Fortran Compiler
568                     # "$<$<COMPILE_LANG_AND_ID:Fortran,MSVC>:>"                                   #@ Microsoft Visual Studio
569                     "$<$<COMPILE_LANG_AND_ID:Fortran,NVHPC>:-r${RWORDSIZE};-i4>"                #@ NVIDIA HPC Compiler
570                     # "$<$<COMPILE_LANG_AND_ID:Fortran,NVIDIA>:>"                                 #@ NVIDIA CUDA Compiler
571                     # "$<$<COMPILE_LANG_AND_ID:Fortran,OpenWatcom>:>"                             #@ Open Watcom
572                     "$<$<COMPILE_LANG_AND_ID:Fortran,PGI>:-r${RWORDSIZE};-i4>"                  #@ The Portland Group
573                     "$<$<COMPILE_LANG_AND_ID:Fortran,PathScale>:-r${RWORDSIZE};-i4>"            #@ PathScale
574                     # "$<$<COMPILE_LANG_AND_ID:Fortran,SDCC>:>"                                   #@ Small Device C Compiler
575                     # "$<$<COMPILE_LANG_AND_ID:Fortran,SunPro>:>"                                 #@ Oracle Solaris Studio
576                     # "$<$<COMPILE_LANG_AND_ID:Fortran,Tasking>:>"                                #@ Tasking Compiler Toolsets
577                     # "$<$<COMPILE_LANG_AND_ID:Fortran,TI>:>"                                     #@ Texas Instruments
578                     # "$<$<COMPILE_LANG_AND_ID:Fortran,TinyCC>:>"                                 #@ Tiny C Compiler
579                     "$<$<COMPILE_LANG_AND_ID:Fortran,XL>:-qrealsize=${RWORDSIZE};-qintsize=4>"  #@ IBM XL
580                     # "$<$<COMPILE_LANG_AND_ID:Fortran,XLClang>:>"                                #@ IBM Clang-based XL
581                     # "$<$<COMPILE_LANG_AND_ID:Fortran,IBMClang>:>"                               #@ IBM LLVM-based Compiler
582                     # Todo find how to handle default selection or add new compiler IDs
583                     # unknown how to add support for sxf90
585                     # line lengths
586                     "$<$<COMPILE_LANG_AND_ID:Fortran,GNU>:-ffree-line-length-none>"                #@ GNU Compiler Collection
587                     )
590 # https://stackoverflow.com/a/53155812
591 # set( Fortran_COMPILER_ID ${CMAKE_Fortran_COMPILER_ID} )
592 # message( STATUS "Set Fortran_COMPILER_ID to : ${Fortran_COMPILER_ID}" )
595 # Whole project flags
596 add_compile_options(
597                     # $<$<COMPILE_LANGUAGE:Fortran>:-cpp>
598                     # Use "" and ; specifically to evaluate correctly
599                     "$<$<COMPILE_LANG_AND_ID:Fortran,Intel>:-diag-disable;6843>"
600                     $<$<AND:$<COMPILE_LANG_AND_ID:Fortran,GNU>,$<VERSION_GREATER_EQUAL:${CMAKE_Fortran_COMPILER_VERSION},10>>:-fallow-argument-mismatch>
601                     $<$<AND:$<COMPILE_LANG_AND_ID:Fortran,GNU>,$<VERSION_GREATER_EQUAL:${CMAKE_Fortran_COMPILER_VERSION},10>>:-fallow-invalid-boz>
602                     $<$<AND:$<COMPILE_LANG_AND_ID:Fortran,GNU>,$<VERSION_GREATER_EQUAL:${CMAKE_Fortran_COMPILER_VERSION},10>>:-ffree-line-length-none>
604                     # $<AND:$<COMPILE_LANGUAGE:Fortran>,$<STREQUAL:${Fortran_COMPILER_ID},Intel>:-diag-disable;6843>
605                     )
607 if ( ${PROFILE_COMPILATION} )
608   message( STATUS "Attemping to add compilation profiling..." )
609   add_compile_options(
610                       $<$<COMPILE_LANG_AND_ID:Fortran,GNU>:-ftime-report>
611                       )
612 endif()
614 add_compile_definitions(
615                         MAX_DOMAINS_F=${MAX_DOMAINS_F}
616                         CONFIG_BUF_LEN=${CONFIG_BUF_LEN}
617                         MAX_HISTORY=${MAX_HISTORY}
618                         IWORDSIZE=${IWORDSIZE}
619                         DWORDSIZE=${DWORDSIZE}
620                         LWORDSIZE=${LWORDSIZE}
621                         RWORDSIZE=${RWORDSIZE}
622                         # Only define if set, this is to use #ifdef/#ifndef preprocessors
623                         # in code since cmake cannot handle basically any others :(
624                         # https://gitlab.kitware.com/cmake/cmake/-/issues/17398
625                         $<$<BOOL:${ENABLE_CHEM}>:WRF_CHEM=$<BOOL:${ENABLE_CHEM}>>
626                         $<$<BOOL:${ENABLE_CHEM}>:BUILD_CHEM=$<BOOL:${ENABLE_CHEM}>>
627                         $<$<BOOL:${ENABLE_CMAQ}>:WRF_CMAQ=$<BOOL:${ENABLE_CMAQ}>>
628                         $<$<AND:$<BOOL:${ENABLE_CHEM}>,$<BOOL:${ENABLE_KPP}>>:WRF_KPP=$<BOOL:${ENABLE_KPP}>>
629                         $<$<BOOL:${ENABLE_DFI_RADAR}>:WRF_DFI_RADAR=$<BOOL:${ENABLE_DFI_RADAR}>>
630                         $<$<BOOL:${ENABLE_TITAN}>:WRF_TITAN=$<BOOL:${ENABLE_TITAN}>>
631                         $<$<BOOL:${ENABLE_MARS}>:WRF_MARS=$<BOOL:${ENABLE_MARS}>>
632                         $<$<BOOL:${ENABLE_VENUS}>:WRF_VENUS=$<BOOL:${ENABLE_VENUS}>>
633                         $<$<BOOL:${ENABLE_HYDRO}>:WRF_HYDRO=$<BOOL:${ENABLE_HYDRO}>>
635                         # Because once again we need two defines to control one thing
636                         $<$<BOOL:${ENABLE_CTSM}>:WRF_USE_CTSM=$<BOOL:${ENABLE_CTSM}>>
637                         $<$<NOT:$<BOOL:${ENABLE_CTSM}>>:WRF_USE_CLM>
639                         # If force classic or no nc-4 support enable classic
640                         $<$<OR:$<BOOL:${FORCE_NETCDF_CLASSIC}>,$<NOT:$<BOOL:${netCDF_NC4}>>>:NETCDF_classic=1>
641                         $<$<OR:$<BOOL:${WRFIO_NCD_NO_LARGE_FILE_SUPPORT}>,$<NOT:$<BOOL:${netCDF_LARGE_FILE_SUPPORT}>>>:WRFIO_NCD_NO_LARGE_FILE_SUPPORT=1>
642                         # May need a check for WRFIO_ncdpar_LARGE_FILE_SUPPORT
644                         # Now set the opposite in different defines, because why not :)
645                         $<$<AND:$<NOT:$<BOOL:${FORCE_NETCDF_CLASSIC}>>,$<BOOL:${netCDF_NC4}>>:USE_NETCDF4_FEATURES=1>
646                         $<$<AND:$<NOT:$<BOOL:${WRFIO_NCD_NO_LARGE_FILE_SUPPORT}>>,$<BOOL:${netCDF_LARGE_FILE_SUPPORT}>>:WRFIO_NCD_LARGE_FILE_SUPPORT=1>
648                         # Could simplify logic to just check if RPC is available but to be explicit
649                         # Does this actually need to check for EM_CORE (Config.pl:443)
650                         # not enable terran or not rpc_found do
651                         # not ( enable terrain and rpc_found )
652                         $<$<NOT:$<AND:$<BOOL:${ENABLE_TERRAIN}>,$<BOOL:${RPC_FOUND}>>>:LANDREAD_STUB>
653                         $<$<BOOL:${ENABLE_TERRAIN}>:TERRAIN_AND_LANDUSE>
656                         $<$<BOOL:${USE_ALLOCATABLES}>:USE_ALLOCATABLES>
657                         $<$<BOOL:${wrfmodel}>:wrfmodel>
658                         $<$<BOOL:${GRIB1}>:GRIB1>
659                         $<$<BOOL:${INTIO}>:INTIO>
660                         $<$<BOOL:${KEEP_INT_AROUND}>:KEEP_INT_AROUND>
661                         $<$<BOOL:${LIMIT_ARGS}>:LIMIT_ARGS>
663                         #!TODO Always defined - fix the ambiguous english in these BUILD_*_FAST defines
664                         BUILD_RRTMG_FAST=$<BOOL:${BUILD_RRTMG_FAST}>
665                         BUILD_RRTMK=$<BOOL:${BUILD_RRTMK}>
666                         BUILD_SBM_FAST=$<BOOL:${BUILD_SBM_FAST}>
667                         SHOW_ALL_VARS_USED=$<BOOL:${SHOW_ALL_VARS_USED}>
669                         # Alwasys set
670                         NMM_CORE=$<BOOL:${NMM_CORE}>
671                         NMM_MAX_DIM=2600
672                         NETCDF
674                         #!TODO Change this to a confcheck
675                         NONSTANDARD_SYSTEM_SUBR
677                         EM_CORE=${EM_CORE}
678                         WRFPLUS=$<BOOL:$<STREQUAL:${WRF_CORE},"PLUS">>
679                         DA_CORE=$<BOOL:$<OR:$<STREQUAL:${WRF_CORE},"DA_CORE">,$<STREQUAL:${WRF_CORE},"DA_4D_VAR">>>
680                         # DFI_RADAR=$<BOOL:${NMM_CORE}>
682                         # Nesting options
683                         $<$<BOOL:${MOVE_NESTS}>:MOVE_NESTS>
684                         $<$<BOOL:$<STREQUAL:${WRF_NESTING},"VORTEX">>:VORTEX_CENTER>
686                         # Configuration checks
687                         $<$<NOT:$<BOOL:${Fortran_2003_IEEE}>>:NO_IEEE_MODULE>
688                         $<$<NOT:$<BOOL:${Fortran_2003_ISO_C}>>:NO_ISO_C_SUPPORT>
689                         # If flush fails, check if we can fall back to fflush, and if not no support
690                         $<$<NOT:$<BOOL:${Fortran_2003_FLUSH}>>:$<IF:$<BOOL:${Fortran_2003_FFLUSH}>,USE_FFLUSH,NO_FLUSH_SUPPORT>>
691                         $<$<NOT:$<BOOL:${Fortran_2003_GAMMA}>>:NO_GAMMA_SUPPORT>
693                         #!TODO Leaving as is in WRF for now but investigate why we don't do this
694                         # https://stackoverflow.com/a/1035713
695                         # If fseeko64 succeeds, use that, else check if we can fall back to fseeko, and if not just use fseek
696                         $<IF:$<BOOL:${FSEEKO64}>,FSEEKO64_OK,$<IF:$<BOOL:${FSEEKO}>,FSEEKO_OK,FSEEK_OK>>
698                         # I don't believe these are used anymore...
699                         # $<$<BOOL:${MPI2_SUPPORT}>:MPI2_SUPPORT=$<BOOL:${MPI2_SUPPORT}>>
700                         # $<$<BOOL:${MPI2_THREAD_SUPPORT}>:MPI2_THREAD_SUPPORT=$<BOOL:${MPI2_THREAD_SUPPORT}>>
702                         )
705 # Make core target
706 add_library(
707             ${PROJECT_NAME}_Core
708               STATIC
709               )
711 # Supplemental to core, or rather should be, some stuff in external is legitimately part of WRF and others
712 # are source code from truly external repositories - albeit old versions
713 add_subdirectory( external )
714 add_subdirectory( tools    )
716 # add_dependencies() does not support generator expressions so whatever we can defer to linking please do so
717 add_dependencies(
718                   ${PROJECT_NAME}_Core
719                   # So many things depend on this that I'm adding a dep here
720                   registry_code
721                   )
722 target_include_directories(
723                             ${PROJECT_NAME}_Core
724                             PUBLIC
725                               # List module directories first so the compiler does not get confused
726                               # about things "not being compiled yet" - yes, yes it is compiled
727                               # These are already set up to be @ install location
728                               $<TARGET_PROPERTY:esmf_time_f90,Fortran_MODULE_DIRECTORY>
729                               $<TARGET_PROPERTY:io_grib_share,Fortran_MODULE_DIRECTORY>
730                               $<TARGET_PROPERTY:io_grib1,Fortran_MODULE_DIRECTORY>
731                               $<TARGET_PROPERTY:fftpack5,Fortran_MODULE_DIRECTORY>
732                               $<TARGET_PROPERTY:io_netcdf,Fortran_MODULE_DIRECTORY>
733                               $<TARGET_PROPERTY:io_int,Fortran_MODULE_DIRECTORY>
735                               $<TARGET_PROPERTY:${PROJECT_NAME}_Core,Fortran_MODULE_DIRECTORY>
738                               $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
739                               $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/inc>
740                               $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/frame>
741                               $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/external/ioapi_share>
743                               $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/inc>
744                               $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/frame>
746                               # For install interface includes, i.e. when used by external tools
747                               # such as WPS
748                               # $<INSTALL_INTERFACE::${PROJECT_SOURCE_DIR}>
749                               $<INSTALL_INTERFACE:include/inc>
750                               $<INSTALL_INTERFACE:include/frame>
751                               $<INSTALL_INTERFACE:include/external/ioapi_share>
753                               # May or may not exist
754                               $<$<TARGET_EXISTS:atm_ocn>:$<TARGET_PROPERTY:atm_ocn,Fortran_MODULE_DIRECTORY>>
755                               $<$<TARGET_EXISTS:io_adios2>:$<TARGET_PROPERTY:io_adios2,Fortran_MODULE_DIRECTORY>>
756                               $<$<TARGET_EXISTS:io_esmf>:$<TARGET_PROPERTY:io_esmf,Fortran_MODULE_DIRECTORY>>
757                               $<$<TARGET_EXISTS:io_pio>:$<TARGET_PROPERTY:io_pio,Fortran_MODULE_DIRECTORY>>
758                               $<$<TARGET_EXISTS:io_netcdfpar>:$<TARGET_PROPERTY:io_netcdfpar,Fortran_MODULE_DIRECTORY>>
759                               $<$<TARGET_EXISTS:io_pnetcdf>:$<TARGET_PROPERTY:io_pnetcdf,Fortran_MODULE_DIRECTORY>>
760                               $<$<TARGET_EXISTS:io_phdf5>:$<TARGET_PROPERTY:io_phdf5,Fortran_MODULE_DIRECTORY>>
761                               $<$<TARGET_EXISTS:g2lib>:$<TARGET_PROPERTY:g2lib,Fortran_MODULE_DIRECTORY>>
762                               $<$<TARGET_EXISTS:bacio-1.3>:$<TARGET_PROPERTY:bacio-1.3,Fortran_MODULE_DIRECTORY>>
764                             PRIVATE
765                               
766                               ${PROJECT_SOURCE_DIR}/dyn_em
768                               # externals
769                               ${PROJECT_SOURCE_DIR}/external/esmf_time_f90
770                               ${PROJECT_SOURCE_DIR}/external/io_grib_share
771                               ${PROJECT_SOURCE_DIR}/external/io_netcdf
772                               ${PROJECT_SOURCE_DIR}/external/io_int
774                               # Found Packages not handled through :: imported target
775                               ${netCDF_INCLUDE_DIRS}
776                               ${netCDF-Fortran_INCLUDE_DIRS}
777                               ${pnetCDF_INCLUDE_DIRS}
778                             )
780 # Add directly to core
781 add_subdirectory( phys     )
782 add_subdirectory( share    )
783 add_subdirectory( frame    )
784 add_subdirectory( inc      )
786 if ( ${WRF_CHEM} )
787   add_subdirectory( chem     )
788 endif()
790 if ( ${ENABLE_HYDRO} )
791   add_subdirectory( hydro  )
792 endif()
794 add_subdirectory( dyn_em   )
797 add_subdirectory( main     )
799 ################################################################################
800 # Add subdirectory with case info
801 ################################################################################
802 if ( ${CURRENT_WRF_CORE_IDX} GREATER_EQUAL ${START_DA_IDX} )
803   message( STATUS "DA or PLUS build, WRF_CASE selection ignored" )
804 else()
805   add_subdirectory( test/${WRF_CASE_FOLDER} )
806 endif()
808 # Configure core
809 set_target_properties(
810                       ${PROJECT_NAME}_Core
811                         PROPERTIES
812                           # Just dump everything in here
813                           Fortran_MODULE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/modules/
814                           Fortran_FORMAT           FREE
815                           EXPORT_PROPERTIES        Fortran_MODULE_DIRECTORY
816                       )
818 # Because of the way netCDF provides its info and the way cmake auto-gens RPATH, we need to help it along
819 target_link_directories(
820                         ${PROJECT_NAME}_Core
821                         PUBLIC
822                           ${netCDF_LIBRARY_DIR}
823                           ${netCDF-Fortran_LIBRARY_DIR}
824                         )
827 target_link_libraries(  ${PROJECT_NAME}_Core
828                           PUBLIC
829                             ${netCDF_LIBRARIES}
830                             ${netCDF-Fortran_LIBRARIES}
831                             ${pnetCDF_LIBRARIES}
832                             $<$<BOOL:${USE_MPI}>:$<TARGET_NAME_IF_EXISTS:MPI::MPI_Fortran>>
833                             $<$<BOOL:${USE_OPENMP}>:$<TARGET_NAME_IF_EXISTS:OpenMP::OpenMP_Fortran>>
834                             # This will add in target dependencies if they exist
835                             $<TARGET_NAME_IF_EXISTS:Jasper::Jasper>
836                             $<TARGET_NAME_IF_EXISTS:HDF5::HDF5>
837                             $<TARGET_NAME_IF_EXISTS:ZLIB::ZLIB>
838                             $<TARGET_NAME_IF_EXISTS:CURL::libcurl>
839                             $<TARGET_NAME_IF_EXISTS:RPC::RPC>
840                           PRIVATE
843                             # "External" io libs
844                             esmf_time_f90
846                             io_grib1
847                             grib1_util
848                             MEL_grib1
849                             WGRIB
851                             io_grib_share
852                             fftpack5
854                             $<TARGET_NAME_IF_EXISTS:wrfhydro>
855                             $<TARGET_NAME_IF_EXISTS:atm_ocn>
856                             $<TARGET_NAME_IF_EXISTS:io_adios2>
857                             $<TARGET_NAME_IF_EXISTS:io_esmf>
858                             $<TARGET_NAME_IF_EXISTS:io_pio>
859                             io_int
860                             io_netcdf
861                             $<TARGET_NAME_IF_EXISTS:io_netcdfpar>
862                             $<TARGET_NAME_IF_EXISTS:io_pnetcdf>
863                             $<TARGET_NAME_IF_EXISTS:io_phdf5>
865                             $<TARGET_NAME_IF_EXISTS:g2lib>
866                             $<TARGET_NAME_IF_EXISTS:bacio-1.3>
868                             $<TARGET_NAME_IF_EXISTS:RSL_LITE>
869                       )
871 ################################################################################
873 ## Install and export
875 ################################################################################
876 set( CONFIG_INSTALL_DIRECTORY lib/cmake/${PROJECT_NAME} )
877 install(
878         TARGETS ${PROJECT_NAME}_Core
879         EXPORT ${EXPORT_NAME}Targets
880         RUNTIME DESTINATION bin/
881         ARCHIVE DESTINATION lib/
882         LIBRARY DESTINATION lib/
883         )
885 # Install to namespace
886 install(
887         EXPORT      ${EXPORT_NAME}Targets
888         DESTINATION ${CONFIG_INSTALL_DIRECTORY}
889         FILE        ${EXPORT_NAME}Targets.cmake
890         NAMESPACE   ${EXPORT_NAME}::
891         )
893 configure_package_config_file(
894                               ${PROJECT_SOURCE_DIR}/cmake/template/${EXPORT_NAME}Config.cmake.in
895                               ${CMAKE_BINARY_DIR}/${EXPORT_NAME}Config.cmake
896                               INSTALL_DESTINATION ${CONFIG_INSTALL_DIRECTORY}
897                               )
899 write_basic_package_version_file(
900                                   ${CMAKE_BINARY_DIR}/${EXPORT_NAME}ConfigVersion.cmake
901                                   VERSION ${PROJECT_VERSION}
902                                   #!TODO Check if this is the type of versioning support we want to use
903                                   COMPATIBILITY SameMinorVersion
904                                   )
906 install(
907         FILES
908           ${CMAKE_BINARY_DIR}/${EXPORT_NAME}Config.cmake
909           ${CMAKE_BINARY_DIR}/${EXPORT_NAME}ConfigVersion.cmake
910         DESTINATION ${CONFIG_INSTALL_DIRECTORY}
911         )
913 # Install some helper files for anyone using this build as part of their code
914 install(
915         DIRECTORY
916           # Trailing / is important
917           ${PROJECT_SOURCE_DIR}/cmake/modules/
918         COMPONENT       helpers
919         DESTINATION     share
920         FILES_MATCHING
921           PATTERN       "*.cmake"
922         )
923 install(
924         FILES
925           ${PROJECT_SOURCE_DIR}/cmake/confcheck.cmake
926           ${PROJECT_SOURCE_DIR}/cmake/gitinfo.cmake
927           ${PROJECT_SOURCE_DIR}/cmake/printOption.cmake
928           ${PROJECT_SOURCE_DIR}/cmake/wrf_get_version.cmake
929         COMPONENT     helpers
930         DESTINATION   share
931         )