-
Notifications
You must be signed in to change notification settings - Fork 594
Expand file tree
/
Copy pathmodule.cmake
More file actions
382 lines (343 loc) · 14.2 KB
/
module.cmake
File metadata and controls
382 lines (343 loc) · 14.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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# copyright 2019 Spilsbury Holdings
#
# usage: barretenberg_module(module_name [dependencies ...])
#
# Scans for all .cpp files in a subdirectory, and creates a library named <module_name>.
# Scans for all .test.cpp files in a subdirectory, and creates a gtest binary named <module name>_tests.
# Scans for all .bench.cpp files in a subdirectory, and creates a benchmark binary named <module name>_bench.
#
# We have to get a bit complicated here, due to the fact CMake will not parallelize the building of object files
# between dependent targets, due to the potential of post-build code generation steps etc.
# To work around this, we create "object libraries" containing the object files.
# Then we declare executables/libraries that are to be built from these object files.
# These assets will only be linked as their dependencies complete, but we can parallelize the compilation at least.
# This is an interface library that can be used as an install target to include all header files
# encountered by the `barretenberg_module` function. There is probably a better way to do this,
# especially if we want to exclude some of the header files being installed
add_library(barretenberg_headers INTERFACE)
target_sources(
barretenberg_headers
INTERFACE
FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src
)
# barretenberg_module variant that allows specifying custom source and header files
function(barretenberg_module_with_sources MODULE_NAME)
# Parse named arguments for SOURCE_FILES and HEADER_FILES
# All remaining arguments are treated as dependencies
set(options "")
set(oneValueArgs "")
set(multiValueArgs SOURCE_FILES HEADER_FILES TEST_SOURCE_FILES BENCH_SOURCE_FILES FUZZERS_SOURCE_FILES DEPENDENCIES)
cmake_parse_arguments(PARSE_ARGV 1 ARG "${options}" "${oneValueArgs}" "${multiValueArgs}")
# Use provided SOURCE_FILES and HEADER_FILES
set(SOURCE_FILES ${ARG_SOURCE_FILES})
set(HEADER_FILES ${ARG_HEADER_FILES})
set(TEST_SOURCE_FILES ${ARG_TEST_SOURCE_FILES})
set(BENCH_SOURCE_FILES ${ARG_BENCH_SOURCE_FILES})
set(FUZZERS_SOURCE_FILES ${ARG_FUZZERS_SOURCE_FILES})
# Dependencies are either in ARG_DEPENDENCIES or ARG_UNPARSED_ARGUMENTS
set(MODULE_DEPENDENCIES ${ARG_DEPENDENCIES} ${ARG_UNPARSED_ARGUMENTS})
target_sources(
barretenberg_headers
INTERFACE
FILE_SET HEADERS
FILES ${HEADER_FILES}
)
if(SOURCE_FILES)
add_library(
${MODULE_NAME}_objects
OBJECT
EXCLUDE_FROM_ALL
${SOURCE_FILES}
)
list(APPEND lib_targets ${MODULE_NAME}_objects)
add_library(
${MODULE_NAME}
STATIC
$<TARGET_OBJECTS:${MODULE_NAME}_objects>
)
target_link_libraries(
${MODULE_NAME}
PUBLIC
${MODULE_DEPENDENCIES}
${TRACY_LIBS}
${TBB_IMPORTED_TARGETS}
)
if(ENABLE_STACKTRACES)
target_link_libraries(
${MODULE_NAME}_objects
PUBLIC
Backward::Interface
)
target_link_options(
${MODULE_NAME}
PRIVATE
-ldw -lelf
)
endif()
if(FUZZING)
target_compile_options(
${MODULE_NAME}_objects
PRIVATE
-fsanitize=fuzzer-no-link
)
if(FUZZING_AVM)
target_compile_options(
${MODULE_NAME}_objects
PRIVATE
-fsanitize-coverage-ignorelist=${CMAKE_SOURCE_DIR}/cmake/fuzzing-avm-ignorelist.txt
)
endif()
endif()
# enable msgpack downloading via dependency (solves race condition)
add_dependencies(${MODULE_NAME} msgpack-c)
add_dependencies(${MODULE_NAME}_objects msgpack-c)
# enable lmdb downloading via dependency (solves race condition)
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "wasm32" AND NOT BB_LITE)
add_dependencies(${MODULE_NAME} lmdb_repo)
add_dependencies(${MODULE_NAME}_objects lmdb_repo)
endif()
list(APPEND lib_targets ${MODULE_NAME})
set(MODULE_LINK_NAME ${MODULE_NAME})
elseif(MODULE_DEPENDENCIES AND NOT BENCH_SOURCE_FILES AND NOT FUZZERS_SOURCE_FILES)
# Header-only module with dependencies: create an INTERFACE library
# so dependents can still reference this module by name.
add_library(${MODULE_NAME} INTERFACE)
target_link_libraries(${MODULE_NAME} INTERFACE ${MODULE_DEPENDENCIES})
set(MODULE_LINK_NAME ${MODULE_NAME})
endif()
# Test files - only build if TEST_SOURCE_FILES was provided
if(TEST_SOURCE_FILES AND NOT FUZZING)
add_library(
${MODULE_NAME}_test_objects
OBJECT
${TEST_SOURCE_FILES}
)
list(APPEND lib_targets ${MODULE_NAME}_test_objects)
target_link_libraries(
${MODULE_NAME}_test_objects
PRIVATE
${TRACY_LIBS}
GTest::gtest
GTest::gmock_main
${TBB_IMPORTED_TARGETS}
)
add_executable(
${MODULE_NAME}_tests
$<TARGET_OBJECTS:${MODULE_NAME}_test_objects>
)
list(APPEND exe_targets ${MODULE_NAME}_tests)
if(ENABLE_STACKTRACES)
target_link_libraries(
${MODULE_NAME}_test_objects
PUBLIC
Backward::Interface
)
target_link_options(
${MODULE_NAME}_tests
PRIVATE
-ldw -lelf
)
endif()
if(WASM)
target_link_options(
${MODULE_NAME}_tests
PRIVATE
-Wl,-z,stack-size=8388608
)
endif()
if(CI)
target_compile_definitions(
${MODULE_NAME}_test_objects
PRIVATE
-DCI=1
)
endif()
if((COVERAGE AND NOT ENABLE_HEAVY_TESTS) OR (DISABLE_HEAVY_TESTS))
# Heavy tests take hours when we are using profiling instrumentation
target_compile_definitions(
${MODULE_NAME}_test_objects
PRIVATE
)
endif()
target_link_libraries(
${MODULE_NAME}_tests
PRIVATE
${MODULE_LINK_NAME}
${MODULE_DEPENDENCIES}
GTest::gtest
GTest::gtest_main
GTest::gmock_main
${TRACY_LIBS}
${TBB_IMPORTED_TARGETS}
)
# enable msgpack downloading via dependency (solves race condition)
add_dependencies(${MODULE_NAME}_test_objects msgpack-c)
add_dependencies(${MODULE_NAME}_tests msgpack-c)
# enable lmdb downloading via dependency (solves race condition)
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "wasm32" AND NOT BB_LITE)
add_dependencies(${MODULE_NAME}_test_objects lmdb_repo)
add_dependencies(${MODULE_NAME}_tests lmdb_repo)
endif()
if(NOT WASM)
# gtest_discover_tests can't wrap test invocations in wasm-run from ctest, so for
# the wasm preset we expose a `run_<module>_tests` custom target instead and let
# CI / developers invoke it directly.
gtest_discover_tests(${MODULE_NAME}_tests WORKING_DIRECTORY ${CMAKE_BINARY_DIR} TEST_FILTER -*_SKIP_CI* DISCOVERY_TIMEOUT 30)
else()
# Under Emscripten the test binary lands as bin/<module>_tests.js with sibling
# bin/<module>_tests.wasm. wasm-run resolves the .js automatically.
add_custom_target(
run_${MODULE_NAME}_tests
COMMAND ${CMAKE_SOURCE_DIR}/scripts/wasm-run
--dir=$ENV{HOME}/.bb-crs
--dir=${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/bin/${MODULE_NAME}_tests
DEPENDS ${MODULE_NAME}_tests
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMENT "Running ${MODULE_NAME}_tests under wasm-run"
USES_TERMINAL
)
endif()
endif()
# Fuzzer files - only build if FUZZERS_SOURCE_FILES was provided
if(FUZZING AND FUZZERS_SOURCE_FILES)
foreach(FUZZER_SOURCE_FILE ${FUZZERS_SOURCE_FILES})
get_filename_component(FUZZER_NAME_STEM ${FUZZER_SOURCE_FILE} NAME_WE)
add_executable(
${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer
${FUZZER_SOURCE_FILE}
)
list(APPEND exe_targets ${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer)
target_link_options(
${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer
PRIVATE
"-fsanitize=fuzzer"
)
target_compile_options(
${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer
PRIVATE
"-fsanitize=fuzzer"
)
target_link_libraries(
${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer
PRIVATE
${MODULE_LINK_NAME}
${MODULE_DEPENDENCIES}
)
# Record fuzzer metadata for manifest generation
get_filename_component(_fuzzer_dir "${FUZZER_SOURCE_FILE}" DIRECTORY)
file(RELATIVE_PATH _source_path
"${CMAKE_SOURCE_DIR}/src/barretenberg"
"${_fuzzer_dir}")
set_property(GLOBAL APPEND PROPERTY BB_FUZZER_MANIFEST_ENTRIES
"${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer|${_source_path}")
if(ENABLE_STACKTRACES)
target_link_libraries(
${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer
PUBLIC
Backward::Interface
)
target_link_options(
${MODULE_NAME}_${FUZZER_NAME_STEM}_fuzzer
PRIVATE
-ldw -lelf
)
endif()
endforeach()
endif()
# Benchmark files - only build if BENCH_SOURCE_FILES was provided
if(BENCH_SOURCE_FILES AND NOT FUZZING)
foreach(BENCHMARK_SOURCE ${BENCH_SOURCE_FILES})
get_filename_component(BENCHMARK_NAME ${BENCHMARK_SOURCE} NAME_WE) # extract name without extension
add_library(
${BENCHMARK_NAME}_bench_objects
OBJECT
${BENCHMARK_SOURCE}
)
list(APPEND lib_targets ${BENCHMARK_NAME}_bench_objects)
target_link_libraries(
${BENCHMARK_NAME}_bench_objects
PRIVATE
benchmark::benchmark
${TRACY_LIBS}
${TBB_IMPORTED_TARGETS}
)
add_executable(
${BENCHMARK_NAME}_bench
$<TARGET_OBJECTS:${BENCHMARK_NAME}_bench_objects>
)
list(APPEND exe_targets ${MODULE_NAME}_bench)
target_link_libraries(
${BENCHMARK_NAME}_bench
PRIVATE
${MODULE_LINK_NAME}
${MODULE_DEPENDENCIES}
benchmark::benchmark
${TRACY_LIBS}
${TBB_IMPORTED_TARGETS}
)
if(WASM)
# Benchmarks need real filesystem access to read the CRS.
# NODERAWFS=1 is a link-time setting (the env var of the
# same name set by wasm-run is a no-op without it) that
# routes Emscripten file ops to Node's native fs. Pair it
# with PROXY_TO_PTHREAD=0 because NODERAWFS only services
# the Node main thread; under PROXY_TO_PTHREAD wasm `main`
# runs on a worker and every file op silently returns zero
# (see Emscripten #19330). parallel_for can still spawn its
# own workers for multithreaded proving.
target_link_options(
${BENCHMARK_NAME}_bench
PRIVATE
"SHELL:-sNODERAWFS=1"
"SHELL:-sPROXY_TO_PTHREAD=0"
"SHELL:-sALLOW_BLOCKING_ON_MAIN_THREAD=1"
)
endif()
if(ENABLE_STACKTRACES)
target_link_libraries(
${BENCHMARK_NAME}_bench_objects
PUBLIC
Backward::Interface
)
target_link_options(
${BENCHMARK_NAME}_bench
PRIVATE
-ldw -lelf
)
endif()
# enable msgpack downloading via dependency (solves race condition)
add_dependencies(${BENCHMARK_NAME}_bench_objects msgpack-c)
add_dependencies(${BENCHMARK_NAME}_bench msgpack-c)
# enable lmdb downloading via dependency (solves race condition)
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "wasm32" AND NOT BB_LITE)
add_dependencies(${BENCHMARK_NAME}_bench_objects lmdb_repo)
add_dependencies(${BENCHMARK_NAME}_bench lmdb_repo)
endif()
endforeach()
endif()
set(${MODULE_NAME}_lib_targets ${lib_targets} PARENT_SCOPE)
set(${MODULE_NAME}_exe_targets ${exe_targets} PARENT_SCOPE)
endfunction()
function(barretenberg_module MODULE_NAME)
# Auto-discover all source files
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp)
file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.hpp *.tcc)
file(GLOB_RECURSE TEST_SOURCE_FILES CONFIGURE_DEPENDS *.test.cpp)
file(GLOB_RECURSE BENCH_SOURCE_FILES CONFIGURE_DEPENDS *.bench.cpp)
file(GLOB_RECURSE FUZZERS_SOURCE_FILES CONFIGURE_DEPENDS *.fuzzer.cpp)
list(FILTER SOURCE_FILES EXCLUDE REGEX ".*\\.(fuzzer|test|bench)\\.cpp$")
barretenberg_module_with_sources(
${MODULE_NAME}
SOURCE_FILES ${SOURCE_FILES}
HEADER_FILES ${HEADER_FILES}
TEST_SOURCE_FILES ${TEST_SOURCE_FILES}
BENCH_SOURCE_FILES ${BENCH_SOURCE_FILES}
FUZZERS_SOURCE_FILES ${FUZZERS_SOURCE_FILES}
DEPENDENCIES ${ARGN}
)
# Propagate targets to parent scope
set(${MODULE_NAME}_lib_targets ${${MODULE_NAME}_lib_targets} PARENT_SCOPE)
set(${MODULE_NAME}_exe_targets ${${MODULE_NAME}_exe_targets} PARENT_SCOPE)
endfunction()