-
Notifications
You must be signed in to change notification settings - Fork 710
/
Copy pathc_preproc.cmake
128 lines (109 loc) · 5.33 KB
/
c_preproc.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# 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 )
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}
)
# # 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+
# TL;DR - This doesn't work despite all documentation stating otherwise, need to use CMP0118
# set_source_files_properties(
# ${WRF_PP_F_OUTPUT_FILE}
# ${WRF_PP_F_TARGET_DIRECTORY}
# PROPERTIES
# GENERATED TRUE
# )
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
)
# 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}
)
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()