Update version info for release v4.6.1 (#2122)
[WRF.git] / cmake / c_preproc.cmake
blob0d0dd751ef54b969ae2a3826eba92c6c1857e3ec
1 # WRF Macro for C preprocessing F files that are just... bad ifdef usage to say the least
2 macro( wrf_c_preproc_fortran )
4   set( options        )
5   set( oneValueArgs   TARGET_NAME SUFFIX PREFIX EXTENSION OUTPUT_DIR )
6   set( multiValueArgs DEPENDENCIES INCLUDES SOURCES DEFINITIONS TARGET_SCOPE )
8   cmake_parse_arguments(
9                         WRF_PP_F
10                         "${options}"  "${oneValueArgs}"  "${multiValueArgs}"
11                         ${ARGN}
12                         )
14   # Santitize input
15   if ( DEFINED WRF_PP_F_TARGET_SCOPE )
16     set( WRF_PP_F_TARGET_DIRECTORY TARGET_DIRECTORY ${WRF_PP_F_TARGET_SCOPE} )
17   endif()
19   set( WRF_PP_F_INCLUDES_FLAGS )
20   foreach( WRF_PP_F_INC  ${WRF_PP_F_INCLUDES} )
21     list( APPEND WRF_PP_F_INCLUDES_FLAGS -I${WRF_PP_F_INC} )
22   endforeach()
24   wrf_expand_definitions( 
25                           RESULT_VAR   WRF_PP_F_DEFS
26                           DEFINITIONS  ${WRF_PP_F_DEFINITIONS}
27                           )
29   # Generate compile command and file outputs
30   set( WRF_PP_F_OUTPUT   )
31   set( WRF_PP_F_COMMANDS )
32   foreach( WRF_PP_F_SOURCE_FILE  ${WRF_PP_F_SOURCES} )
33     get_filename_component( WRF_PP_F_INPUT_SOURCE           ${WRF_PP_F_SOURCE_FILE} REALPATH )
34     get_filename_component( WRF_PP_F_INPUT_SOURCE_FILE_ONLY ${WRF_PP_F_SOURCE_FILE} NAME     )
36     if ( ${WRF_PP_F_EXTENSION} MATCHES "^[.][a-z0-9]+$" )
37       string( REGEX REPLACE "[.].*$" "${WRF_PP_F_EXTENSION}" WRF_PP_F_OUTPUT_FILE ${WRF_PP_F_INPUT_SOURCE_FILE_ONLY} )
38     else()
39       # Default extension
40       string( REGEX REPLACE "[.].*$" ".i" WRF_PP_F_OUTPUT_FILE ${WRF_PP_F_INPUT_SOURCE_FILE_ONLY} )
41     endif()
43     set( WRF_PP_F_OUTPUT_FILE ${WRF_PP_F_OUTPUT_DIR}/${WRF_PP_F_PREFIX}${WRF_PP_F_OUTPUT_FILE}${WRF_PP_F_SUFFIX} )
45     list( 
46           APPEND WRF_PP_F_COMMANDS 
47           COMMAND ${CMAKE_C_PREPROCESSOR} ${CMAKE_C_PREPROCESSOR_FLAGS} ${WRF_PP_F_INPUT_SOURCE} ${WRF_PP_F_DEFS} ${WRF_PP_F_INCLUDES_FLAGS} > ${WRF_PP_F_OUTPUT_FILE}
48           # Force check that they were made
49           COMMAND ${CMAKE_COMMAND} -E compare_files ${WRF_PP_F_OUTPUT_FILE} ${WRF_PP_F_OUTPUT_FILE}
50           )
51     list( 
52           APPEND WRF_PP_F_OUTPUT
53           ${WRF_PP_F_OUTPUT_FILE}
54           )
55     
56     # # Tell all targets that eventually use this file that it is generated - this is useful if this macro is used in a
57     # # different directory than where the target dependency is set
58     # # Thanks to https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-can-i-add-a-dependency-to-a-source-file-which-is-generated-in-a-subdirectory
59     # # and https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom-commands/
60     # # It keeps getting better lol
61     # # https://gitlab.kitware.com/cmake/cmake/-/issues/18399
62     # # We could use cmake 3.20+ and CMP0118, but this allows usage from 3.18.6+
63     # TL;DR - This doesn't work despite all documentation stating otherwise, need to use CMP0118
64     # set_source_files_properties(
65     #                             ${WRF_PP_F_OUTPUT_FILE}
66     #                             ${WRF_PP_F_TARGET_DIRECTORY}
67     #                             PROPERTIES
68     #                               GENERATED TRUE
69     #                             )
70     set_source_files_properties(
71                                 ${WRF_PP_F_OUTPUT_FILE}
72                                 DIRECTORY ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
73                                 ${WRF_PP_F_TARGET_DIRECTORY}
74                                 PROPERTIES
75                                   Fortran_PREPROCESS OFF
76                                 )
77     # message( STATUS "File ${WRF_PP_F_SOURCE_FILE} will be preprocessed into ${WRF_PP_F_OUTPUT_FILE}" )
79   endforeach()
81   # Preprocess sources into a custom target
82   add_custom_command(
83                       OUTPUT ${WRF_PP_F_OUTPUT}
84                       COMMAND ${CMAKE_COMMAND} -E  make_directory ${WRF_PP_F_OUTPUT_DIR}
85                       ${WRF_PP_F_COMMANDS}
86                       COMMENT "Preprocessing ${WRF_PP_F_TARGET_NAME}"
87                       DEPENDS ${WRF_PP_F_DEPENDENCIES}
88                       )
90   add_custom_target(
91                     ${WRF_PP_F_TARGET_NAME}
92                     COMMENT "Building ${WRF_PP_F_TARGET_NAME}"
93                     DEPENDS ${WRF_PP_F_OUTPUT}
94                     )
96 endmacro()
98 # Helper macro to take current defintions and santize them with -D, compatible with generator expressions
99 # for use when definitions are needed at generation time for custom commands
100 macro( wrf_expand_definitions )
101   set( options        )
102   set( oneValueArgs   RESULT_VAR )
103   set( multiValueArgs DEFINITIONS )
105   cmake_parse_arguments(
106                         WRF_EXP
107                         "${options}"  "${oneValueArgs}"  "${multiValueArgs}"
108                         ${ARGN}
109                         )
111   set( WRF_EXP_DEFS )
112   foreach( WRF_EXP_DEF  ${WRF_EXP_DEFINITIONS} )
113     if ( NOT ${WRF_EXP_DEF} MATCHES ".*-D.*" )
114       # We have a generator expression, error! no way we can evaluate this correctly
115       if ( ${WRF_EXP_DEF} MATCHES "^[$]<" )
116         message( FATAL_ERROR "Generator expressions not allowed in preprocessing defines" )
117       else()
118         list( APPEND WRF_EXP_DEFS -D${WRF_EXP_DEF} )
119       endif()
120     else()
121       # Just add it normally
122       list( APPEND WRF_EXP_DEFS ${WRF_EXP_DEF} )
123     endif()
124     
125   endforeach()
127   set( ${WRF_EXP_RESULT_VAR} ${WRF_EXP_DEFS} )
128 endmacro()