# WRF Macro for C preprocessing F files that are just... bad ifdef usage to say the least macro( wrf_c_preproc_fortran ) set( options ) set( oneValueArgs TARGET_NAME SUFFIX PREFIX EXTENSION OUTPUT_DIR ) set( multiValueArgs DEPENDENCIES INCLUDES SOURCES DEFINITIONS TARGET_SCOPE ) cmake_parse_arguments( WRF_PP_F "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) # Santitize input if ( DEFINED WRF_PP_F_TARGET_SCOPE ) set( WRF_PP_F_TARGET_DIRECTORY TARGET_DIRECTORY ${WRF_PP_F_TARGET_SCOPE} ) endif() set( WRF_PP_F_INCLUDES_FLAGS ) foreach( WRF_PP_F_INC ${WRF_PP_F_INCLUDES} ) list( APPEND WRF_PP_F_INCLUDES_FLAGS -I${WRF_PP_F_INC} ) endforeach() wrf_expand_definitions( RESULT_VAR WRF_PP_F_DEFS DEFINITIONS ${WRF_PP_F_DEFINITIONS} ) # Generate compile command and file outputs set( WRF_PP_F_OUTPUT ) set( WRF_PP_F_COMMANDS ) set( WRF_PP_F_DEPENDS ) foreach( WRF_PP_F_SOURCE_FILE ${WRF_PP_F_SOURCES} ) get_filename_component( WRF_PP_F_INPUT_SOURCE ${WRF_PP_F_SOURCE_FILE} REALPATH ) get_filename_component( WRF_PP_F_INPUT_SOURCE_FILE_ONLY ${WRF_PP_F_SOURCE_FILE} NAME ) if ( ${WRF_PP_F_EXTENSION} MATCHES "^[.][a-z0-9]+$" ) string( REGEX REPLACE "[.].*$" "${WRF_PP_F_EXTENSION}" WRF_PP_F_OUTPUT_FILE ${WRF_PP_F_INPUT_SOURCE_FILE_ONLY} ) else() # Default extension string( REGEX REPLACE "[.].*$" ".i" WRF_PP_F_OUTPUT_FILE ${WRF_PP_F_INPUT_SOURCE_FILE_ONLY} ) endif() set( WRF_PP_F_OUTPUT_FILE ${WRF_PP_F_OUTPUT_DIR}/${WRF_PP_F_PREFIX}${WRF_PP_F_OUTPUT_FILE}${WRF_PP_F_SUFFIX} ) list( APPEND WRF_PP_F_COMMANDS 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} # Force check that they were made COMMAND ${CMAKE_COMMAND} -E compare_files ${WRF_PP_F_OUTPUT_FILE} ${WRF_PP_F_OUTPUT_FILE} ) list( APPEND WRF_PP_F_OUTPUT ${WRF_PP_F_OUTPUT_FILE} ) list( APPEND WRF_PP_F_DEPENDS ${WRF_PP_F_INPUT_SOURCE} ) # # Tell all targets that eventually use this file that it is generated - this is useful if this macro is used in a # # different directory than where the target dependency is set # # 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 # # and https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom-commands/ # # It keeps getting better lol # # https://gitlab.kitware.com/cmake/cmake/-/issues/18399 # # We could use cmake 3.20+ and CMP0118, but this allows usage from 3.18.6+ set_source_files_properties( ${WRF_PP_F_OUTPUT_FILE} DIRECTORY ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${WRF_PP_F_TARGET_DIRECTORY} PROPERTIES Fortran_PREPROCESS OFF GENERATED TRUE ) # message( STATUS "File ${WRF_PP_F_SOURCE_FILE} will be preprocessed into ${WRF_PP_F_OUTPUT_FILE}" ) endforeach() # Preprocess sources into a custom target add_custom_command( OUTPUT ${WRF_PP_F_OUTPUT} COMMAND ${CMAKE_COMMAND} -E make_directory ${WRF_PP_F_OUTPUT_DIR} ${WRF_PP_F_COMMANDS} COMMENT "Preprocessing ${WRF_PP_F_TARGET_NAME}" DEPENDS ${WRF_PP_F_DEPENDENCIES} ${WRF_PP_F_DEPENDS} ) add_custom_target( ${WRF_PP_F_TARGET_NAME} COMMENT "Building ${WRF_PP_F_TARGET_NAME}" DEPENDS ${WRF_PP_F_OUTPUT} ) endmacro() # Helper macro to take current defintions and santize them with -D, compatible with generator expressions # for use when definitions are needed at generation time for custom commands macro( wrf_expand_definitions ) set( options ) set( oneValueArgs RESULT_VAR ) set( multiValueArgs DEFINITIONS ) cmake_parse_arguments( WRF_EXP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) set( WRF_EXP_DEFS ) foreach( WRF_EXP_DEF ${WRF_EXP_DEFINITIONS} ) if ( NOT ${WRF_EXP_DEF} MATCHES ".*-D.*" ) # We have a generator expression, error! no way we can evaluate this correctly if ( ${WRF_EXP_DEF} MATCHES "^[$]<" ) message( FATAL_ERROR "Generator expressions not allowed in preprocessing defines" ) else() list( APPEND WRF_EXP_DEFS -D${WRF_EXP_DEF} ) endif() else() # Just add it normally list( APPEND WRF_EXP_DEFS ${WRF_EXP_DEF} ) endif() endforeach() set( ${WRF_EXP_RESULT_VAR} ${WRF_EXP_DEFS} ) endmacro()