-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy pathpodioMacros.cmake
More file actions
332 lines (301 loc) · 15.2 KB
/
Copy pathpodioMacros.cmake
File metadata and controls
332 lines (301 loc) · 15.2 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#---------------------------------------------------------------------------------------------------
#---PODIO_GENERATE_DICTIONARY( dictionary headerfiles SELECTION selectionfile OPTIONS opt1 opt2 ...
# DEPENDS dependency1 dependency2 ...
# )
# if dictionary is a TARGET (e.g., created with add_library), we inherit the INCLUDE_DIRECTORES and
# COMPILE_DEFINITIONS properties
#
# This is effectively a wrapper around REFLEX_GENERATE_DICTIONARY from the RootMacros.
#
# Originally this was a re-implementation / backporting of that to deal with
# oler ROOT versions, but since we now depend on a newer ROOT version in any
# case we keep this to not break the CMake API of podio.
# ---------------------------------------------------------------------------------------------------
function(PODIO_GENERATE_DICTIONARY dictionary)
REFLEX_GENERATE_DICTIONARY(${ARGV})
# Dictionary payloads become very large for our generated EDMs, so we
# explicitly silence this warning here.
set_source_files_properties(${gensrcdict}
PROPERTIES
GENERATED TRUE
COMPILE_FLAGS "-Wno-overlength-strings"
)
# We are not going to be able to fix these in any case, so disable clang-tidy
# for the generated dictionaries
set_target_properties(${dictionary} PROPERTIES CXX_CLANG_TIDY "")
endfunction()
set(PODIO_USE_CLANG_FORMAT AUTO CACHE STRING "Try to use clang-format to format the code generated by podio")
set_property(CACHE PODIO_USE_CLANG_FORMAT PROPERTY STRINGS AUTO ON OFF)
#---------------------------------------------------------------------------------------------------
#---PODIO_GENERATE_DATAMODEL( datamodel YAML_FILE RETURN_HEADERS RETURN_SOURCES
# OUTPUT_FOLDER output_directory
# IO_BACKEND_HANDLERS io_handlers
# )
#
# Arguments:
# datamodel Name of the datamodel to be created. a TARGET "create${datamodel}" will be created
# YAML_FILE The path to the yaml file describing the datamodel
# RETURN_HEADERS variable that will be filled with the list of created headers files: ${datamodel}/*.h
# RETURN_SOURCES variable that will be filled with the list of created source files : src/*.cc
# Parameters:
# OLD_DESCRIPTION OPTIONAL: The path to the yaml file describing a previous datamodel version
# Cannot be used together with OLD_DESCRIPTIONS
# OLD_DESCRIPTIONS OPTIONAL: List of paths to yaml files describing previous datamodel versions
# Cannot be used together with OLD_DESCRIPTION
# OUTPUT_FOLDER OPTIONAL: The folder in which the output files should be placed
# Default is ${CMAKE_CURRENT_SOURCE_DIR}
# UPSTREAM_EDM OPTIONAL: The upstream edm and its package name that are passed to the
# generator via --upstream-edm
# IO_BACKEND_HANDLERS OPTIONAL: The I/O backend handlers that should be generated. The list is
# passed directly to podio_class_generator.py and validated there
# Default is ROOT
# SCHEMA_EVOLUTION OPTIONAL: The path to the yaml file declaring the necessary schema evolution
# LANG OPTIONAL: The programming language choice
# Default is cpp
# DEPENDS OPTIONAL: List of files to be added as configure dependencies of the datamodel
# VERSION OPTIONAL: The version of the datamodel (which does not have to be the schema version!)
# )
#
# Note that the create_${datamodel} target will always be called, but if the YAML_FILE has not changed
# this is essentially a no-op, and should not cause re-compilation.
#---------------------------------------------------------------------------------------------------
function(PODIO_GENERATE_DATAMODEL datamodel YAML_FILE RETURN_HEADERS RETURN_SOURCES)
CMAKE_PARSE_ARGUMENTS(ARG "" "OLD_DESCRIPTION;OUTPUT_FOLDER;UPSTREAM_EDM;SCHEMA_EVOLUTION" "IO_BACKEND_HANDLERS;LANG;DEPENDS;VERSION;OLD_DESCRIPTIONS" ${ARGN})
IF(NOT ARG_OUTPUT_FOLDER)
SET(ARG_OUTPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
ENDIF()
SET(UPSTREAM_EDM_ARG "")
IF (ARG_UPSTREAM_EDM)
SET(UPSTREAM_EDM_ARG "--upstream-edm=${ARG_UPSTREAM_EDM}")
ENDIF()
# Check that OLD_DESCRIPTION and OLD_DESCRIPTIONS are not both set
IF (ARG_OLD_DESCRIPTION AND ARG_OLD_DESCRIPTIONS)
MESSAGE(FATAL_ERROR "OLD_DESCRIPTION and OLD_DESCRIPTIONS cannot be set simultaneously")
ENDIF()
SET(OLD_DESCRIPTION_ARG "")
IF (ARG_OLD_DESCRIPTION)
SET(OLD_DESCRIPTION_ARG "--old-descriptions" "${ARG_OLD_DESCRIPTION}")
ELSEIF (ARG_OLD_DESCRIPTIONS)
SET(OLD_DESCRIPTION_ARG "--old-descriptions")
LIST(APPEND OLD_DESCRIPTION_ARG ${ARG_OLD_DESCRIPTIONS})
ENDIF()
IF(NOT ARG_IO_BACKEND_HANDLERS)
# At least build the ROOT selection.xml by default for now
SET(ARG_IO_BACKEND_HANDLERS "ROOT")
ENDIF()
# Check if the LANG argument is specified and set the language accordingly.
IF(ARG_LANG)
SET(LANGUAGE_ARG "--lang=${ARG_LANG}")
ELSE()
SET(LANGUAGE_ARG "--lang=cpp") # Default to C++
ENDIF()
SET(SCHEMA_EVOLUTION_ARG "")
IF (ARG_SCHEMA_EVOLUTION)
SET(SCHEMA_EVOLUTION_ARG "--evolution_file=${ARG_SCHEMA_EVOLUTION}")
ENDIF()
set(CLANG_FORMAT_ARG "")
if (PODIO_USE_CLANG_FORMAT STREQUAL AUTO OR PODIO_USE_CLANG_FORMAT)
find_program(CLANG_FORMAT_EXE NAMES "clang-format")
find_file(CLANG_FORMAT_FILE .clang-format PATH ${PROJECT_SOURCE_DIR} NO_DEFAULT_PATH)
# only newer versions of clang-format know about fallback-style.
execute_process(COMMAND ${CLANG_FORMAT_EXE} --fallback-style OUTPUT_VARIABLE CLANG_FALLBACK_STYLE ERROR_VARIABLE CLANG_FALLBACK_STYLE_ERR)
if(CLANG_FORMAT_EXE AND CLANG_FORMAT_FILE
AND NOT ${CLANG_FALLBACK_STYLE_ERR} MATCHES "Unknown")
message(STATUS "Found .clang-format file and clang-format executable. Will pass it to podio class generator")
set(CLANG_FORMAT_ARG "--clangformat")
else()
if(NOT CLANG_FORMAT_EXE)
message(STATUS "Could not find clang-format executable!")
endif()
if(NOT CLANG_FORMAT_FILE)
message(STATUS "Could not find .clang-format file!")
endif()
if(${CLANG_FALLBACK_STYLE_ERR} MATCHES "Unknown")
message(STATUS "Newer version of clang-format required - cannot run with --fallback-style!")
endif()
if(PODIO_USE_CLANG_FORMAT STREQUAL AUTO)
message(STATUS "Skip formatting of generated code files.")
elseif(PODIO_USE_CLANG_FORMAT)
message(FATAL_ERROR "Could not run clang-format on generated code files!")
endif()
endif()
endif()
set(VERSION_ARG "")
if (ARG_VERSION)
set(VERSION_ARG "--datamodel-version=${ARG_VERSION}")
endif()
# Make sure that we re run the generation process every time either the
# templates or the yaml file changes.
include(${podio_PYTHON_DIR}/templates/CMakeLists.txt)
set_property(
DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
${YAML_FILE}
${PODIO_TEMPLATES}
${podio_PYTHON_DIR}/podio_class_generator.py
${podio_PYTHON_DIR}/podio_schema_evolution.py
${podio_PYTHON_DIR}/podio_gen/generator_utils.py
${podio_PYTHON_DIR}/podio_gen/podio_config_reader.py
${podio_PYTHON_DIR}/podio_gen/generator_base.py
${podio_PYTHON_DIR}/podio_gen/cpp_generator.py
${podio_PYTHON_DIR}/podio_gen/julia_generator.py
${ARG_DEPENDS}
)
message(STATUS "Creating '${datamodel}' datamodel")
# we need to bootstrap the data model, so this has to be executed in the cmake run
execute_process(
COMMAND ${Python3_EXECUTABLE} ${podio_PYTHON_DIR}/podio_class_generator.py ${CLANG_FORMAT_ARG} ${SCHEMA_EVOLUTION_ARG} ${UPSTREAM_EDM_ARG} ${YAML_FILE} ${ARG_OUTPUT_FOLDER} ${datamodel} ${ARG_IO_BACKEND_HANDLERS} ${LANGUAGE_ARG} ${VERSION_ARG} ${OLD_DESCRIPTION_ARG}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE podio_generate_command_retval
)
IF(NOT ${podio_generate_command_retval} EQUAL 0)
message(FATAL_ERROR "Could not generate datamodel '${datamodel}'. Check your definition in '${YAML_FILE}'")
ENDIF()
# Get the generated headers and source files
include(${ARG_OUTPUT_FOLDER}/podio_generated_files.cmake)
set (${RETURN_HEADERS} ${headers} PARENT_SCOPE)
set (${RETURN_SOURCES} ${sources} PARENT_SCOPE)
endfunction()
#---------------------------------------------------------------------------------------------------
#---PODIO_ADD_DATAMODEL_CORE_LIB( lib_name HEADERS SOURCES
# OUTPUT_FOLDER output_directory
# )
#
# Add the core datamodel library linking only to the core podio::podio library
# without any I/O backend specific dependencies.
#
# Arguments:
# lib_name Name of the library
# HEADERS The list of all header files created by PODIO_GENERATE_DATAMODEL
# SOURCES The list of all source files created by PODIO_GENERATE_DATAMODEL
#
# Parameters:
# OUTPUT_FOLDER OPTIONAL: The folder in which the output files have been placed by PODIO_GENERATE_DATAMODEL. Defaults to ${CMAKE_CURRENT_SOURCE_DIR}
#---------------------------------------------------------------------------------------------------
function(PODIO_ADD_DATAMODEL_CORE_LIB lib_name HEADERS SOURCES)
CMAKE_PARSE_ARGUMENTS(ARG "" "OUTPUT_FOLDER" "" ${ARGN})
IF(NOT ARG_OUTPUT_FOLDER)
SET(ARG_OUTPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
ENDIF()
# Filter out anything I/O backend related to build the core library
LIST(FILTER HEADERS EXCLUDE REGEX .*SIOBlock.h)
LIST(FILTER HEADERS EXCLUDE REGEX .*ArrowMapper.h)
LIST(FILTER SOURCES EXCLUDE REGEX .*SIOBlock.cc)
add_library(${lib_name} SHARED ${SOURCES} ${HEADERS})
target_link_libraries(${lib_name} PUBLIC podio::podio)
target_include_directories(${lib_name} PUBLIC
$<BUILD_INTERFACE:${ARG_OUTPUT_FOLDER}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
set_target_properties(${lib_name} PROPERTIES
PUBLIC_HEADER "${HEADERS}"
CXX_CLANG_TIDY "" # Do not run clang-tidy on generated sources
# TODO: Update generation to generate compliant code already
)
endfunction()
#---------------------------------------------------------------------------------------------------
#---PODIO_ADD_ROOT_IO_DICT( dict_name CORE_LIB HEADERS SELECTION_XML
# OUTPUT_FOLDER output_directory
# )
#
# Conditionally add the ROOT dictionary to the targets if the corresponding
# selection xml has been generated by PODIO_GENERATE_DATAMODEL.
#
# Arguments:
# dict_name Name of the dictionary
# CORE_LIB The core datamodel library (e.g. from PODIO_ADD_DATAMODEL_CORE_LIB)
# HEADERS The list of all header files generated by PODIO_GENERATE_DATAMODEL
# SELECTION_XML The selection.xml file generated by PODIO_GENERATE_DATAMODEL (either an absolute path or relative to OUTPUT_FOLDER)
#
# Parameters:
# OUTPUT_FOLDER OPTIONAL: The folder in which the output files have been placed by PODIO_GENERATE_DATAMODEL. Defaults to ${CMAKE_CURRENT_SOURCE_DIR}
#---------------------------------------------------------------------------------------------------
function(PODIO_ADD_ROOT_IO_DICT dict_name CORE_LIB HEADERS SELECTION_XML)
CMAKE_PARSE_ARGUMENTS(ARG "" "OUTPUT_FOLDER" "" ${ARGN})
IF(NOT ARG_OUTPUT_FOLDER)
SET(ARG_OUTPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
ENDIF()
IF(IS_ABSOLUTE ${SELECTION_XML})
set(selectionfile ${SELECTION_XML})
ELSE()
set(selectionfile ${ARG_OUTPUT_FOLDER}/${SELECTION_XML})
ENDIF()
IF (NOT EXISTS ${selectionfile})
message(STATUS "Not adding the ROOT dictionaries for ${CORE_LIB}, because \'${selectionfile}\' does not exist")
RETURN()
ENDIF()
# Filter out anything I/O backend related from the generated headers as ROOT only needs
# the core headers
LIST(FILTER HEADERS EXCLUDE REGEX .*SIOBlock.h)
LIST(FILTER HEADERS EXCLUDE REGEX .*ArrowMapper.h)
# Exclude the datamodel header (e.g. edm4hep.h)
# since it will include everything and include guards will be set
# causing clashes with Link type aliases at runtime.
# Find patters like datamodel/datamodel.h or edm4hep/edm4hep.h
# to exclude them
foreach(_header ${HEADERS})
get_filename_component(_header_stem ${_header} NAME_WE)
get_filename_component(_header_dir ${_header} DIRECTORY)
get_filename_component(_parent_name ${_header_dir} NAME)
if(_header_stem STREQUAL _parent_name)
list(REMOVE_ITEM HEADERS ${_header})
break()
endif()
endforeach()
add_library(${dict_name} SHARED)
target_link_libraries(${dict_name} PUBLIC
${CORE_LIB}
podio::podio
ROOT::Core
)
target_include_directories(${dict_name} PUBLIC
$<BUILD_INTERFACE:${ARG_OUTPUT_FOLDER}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_include_directories(${dict_name} SYSTEM PUBLIC
${Python3_INCLUDE_DIRS}
)
PODIO_GENERATE_DICTIONARY(${dict_name} ${HEADERS} SELECTION ${selectionfile}
OPTIONS --library ${CMAKE_SHARED_LIBRARY_PREFIX}${dict_name}${CMAKE_SHARED_LIBRARY_SUFFIX}
)
set_target_properties(${dict_name}-dictgen PROPERTIES EXCLUDE_FROM_ALL TRUE)
add_dependencies(${dict_name} ${CORE_LIB})
endfunction()
#---------------------------------------------------------------------------------------------------
#---PODIO_ADD_SIO_IO_BLOCKS( CORE_LIB HEADERS SOURCES
# OUTPUT_FOLDER output_directory
# )
#
# Conditionally add the SIOBlocks library to the targets if the corresponding
# SIOBlocks code has been generated by PODIO_GENERATE_DATAMODEL. Since the
# runtime loading of the SIOBlocks library follows a naming convention, the name
# of the library cannot be chosen freely, but is instead determined from the
# name of the core datamodel library.
#
# Arguments:
# CORE_LIB The name of the core datamodel library. The name of the SIO Block library target will be ${CORE_LIB}SioBlocks
# HEADERS The list of all header files created by PODIO_GENERATE_DATAMODEL
# SOURCES The list of all source files created by PODIO_GENERATE_DATAMODEL
#
# Parameters:
# OUTPUT_FOLDER OPTIONAL: The folder in which the output files have been placed by PODIO_GENERATE_DATAMODEL. Defaults to ${CMAKE_CURRENT_SOURCE_DIR}
#---------------------------------------------------------------------------------------------------
function(PODIO_ADD_SIO_IO_BLOCKS CORE_LIB HEADERS SOURCES)
CMAKE_PARSE_ARGUMENTS(ARG "" "OUTPUT_FOLDER" "" ${ARGN})
IF(NOT ARG_OUTPUT_FOLDER)
SET(ARG_OUTPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
ENDIF()
# Only get the SIOBlock handlers
LIST(FILTER HEADERS INCLUDE REGEX .*SIOBlock.h)
LIST(FILTER SOURCES INCLUDE REGEX .*SIOBlock.cc)
IF(NOT HEADERS)
MESSAGE(STATUS "Not adding the SIO Blocks library to the targets because the corresponding c++ sources have not been generated")
RETURN()
ENDIF()
add_library(${CORE_LIB}SioBlocks SHARED ${SOURCES} ${HEADERS})
target_link_libraries(${CORE_LIB}SioBlocks PUBLIC ${CORE_LIB} podio::podio podio::podioSioIO SIO::sio)
target_include_directories(${CORE_LIB}SioBlocks PUBLIC
$<BUILD_INTERFACE:${ARG_OUTPUT_FOLDER}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
# Disable clang-tidy on generated sources
set_target_properties(${CORE_LIB}SioBlocks PROPERTIES CXX_CLANG_TIDY "")
endfunction()