-
Notifications
You must be signed in to change notification settings - Fork 132
/
CMakeLists.txt
431 lines (365 loc) · 17.4 KB
/
CMakeLists.txt
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
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
cmake_minimum_required(VERSION 3.22)
project(Tiramisu)
enable_testing()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(PROJECT_DIR ${CMAKE_SOURCE_DIR})
set(CMAKE_VERBOSE_MAKEFILE "ON")
set(CMAKE_EXPORT_COMPILE_COMMANDS "ON")
include(configure.cmake)
if (DEBUG_LEVEL GREATER_EQUAL 1)
set(ENABLE_DEBUG TRUE)
else()
set(ENABLE_DEBUG FALSE)
endif()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(PROJECT_BUILD ${CMAKE_BINARY_DIR})
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)
### FIND EXTERNAL DEPS ###
if (${USE_GPU})
find_package(CUDA REQUIRED)
add_definitions(-DNVCC_PATH="${CUDA_TOOLKIT_ROOT_DIR}/bin/nvcc")
add_library(cuda_wrapper STATIC "src/tiramisu_cuda_wrappers.cpp")
target_link_libraries(cuda_wrapper ${CUDA_LIBRARIES} ${CUDA_CUBLAS_LIBRARIES})
target_include_directories(cuda_wrapper PUBLIC ${CUDA_INCLUDE_DIRS})
if (${USE_CUDNN})
find_library(CUDNN_LIBRARIES cudnn PATHS ${CUDNN_LOCATION}/lib64 NO_DEFAULT_PATH)
set(CUDNN_INCLUDE_DIRECTORY ${CUDNN_LOCATION}/include)
endif()
endif()
if (${USE_MKL_WRAPPERS})
add_library(mkl_wrapper STATIC "src/tiramisu_mkl_wrappers.cpp")
target_include_directories(mkl_wrapper PUBLIC ${MKL_PREFIX}/include)
endif()
macro(init_tags)
set(is_gpu false)
set(is_mpi false)
set(NUM_MPI_RANKS 0)
set(is_cudnn false)
endmacro()
macro(parse_tags tags)
init_tags()
foreach(tag ${tags})
if (${tag} STREQUAL gpu)
set(is_gpu true)
elseif (${tag} STREQUAL mpi)
set(is_mpi true)
elseif (${tag} GREATER -1) # check if it is a number
set(NUM_MPI_RANKS ${tag})
elseif (${tag} STREQUAL cudnn)
set(is_cudnn true)
else()
message(WARNING "Tag ${tag} not recognized")
endif()
endforeach()
endmacro()
# Check that MPI variables are set correctly if we need it
if (${USE_MPI})
if (MPI_BUILD_DIR STREQUAL "")
message(FATAL_ERROR "USE_MPI==true but MPI_BUILD_DIR is empty.")
elseif (MPI_NODES STREQUAL "")
message(FATAL_ERROR "USE_MPI==true but MPI_NODES is empty.")
endif()
endif()
set(CMAKE_CXX_FLAGS "-std=c++17 -Wall -Wno-sign-compare")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
set(CMAKE_CXX_STANDARD 17) # or newer
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS NO)
find_package(Halide REQUIRED)
find_library(ISLLib isl PATHS ${ISL_LIB_DIRECTORY} NO_DEFAULT_PATH)
if (${USE_MPI})
set(CMAKE_CXX_COMPILER "${MPI_BUILD_DIR}/bin/mpicxx")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWITH_MPI")
link_directories(${MPI_BUILD_DIR}/lib)
include_directories(${MPI_BUILD_DIR}/include)
endif()
set(LINK_FLAGS "-ldl -lpthread")
if(${USE_MPI})
set(LINK_FLAGS "${LINK_FLAGS} -lmpi")
endif()
if(${ENABLE_DEBUG})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_DEBUG -DDEBUG_LEVEL=${DEBUG_LEVEL}")
endif()
set(THREADS_PREFER_PTHREAD_FLAG YES)
find_package(Threads REQUIRED)
### Create targets ###
add_subdirectory(src)
if (WITH_PYTHON_BINDINGS)
message(STATUS "Building Python bindings enabled")
add_subdirectory(python_bindings)
target_include_directories(Tiramisu_Python PRIVATE "include")
endif()
## SETUP INSTALLS:
install(TARGETS tiramisu
EXPORT tiramisu_Targets
LIBRARY DESTINATION lib
INCLUDES DESTINATION include
PUBLIC_HEADER DESTINATION include/tiramisu
)
if (USE_AUTO_SCHEDULER)
install(TARGETS tiramisu_auto_scheduler
EXPORT tiramisu_Targets
LIBRARY DESTINATION lib
INCLUDES DESTINATION include
PUBLIC_HEADER DESTINATION include/tiramisu/autoscheduler)
endif()
if (WITH_PYTHON_BINDINGS)
install(FILES ${CMAKE_SOURCE_DIR}/python_bindings/tiramisu.pyi ${CMAKE_SOURCE_DIR}/python_bindings/__init__.py
DESTINATION "${Tiramisu_INSTALL_PYTHONDIR}/tiramisu")
install(TARGETS Tiramisu_Python
EXPORT tiramisu_Targets
LIBRARY DESTINATION "${Tiramisu_INSTALL_PYTHONDIR}/tiramisu")
endif()
### BROKEN: SETUP TESTS/BENCHMARKS/ETC ###
FILE(STRINGS tests/test_list.txt TIRAMISU_TESTS_RAW)
FILE(STRINGS benchmarks/benchmark_list.txt TIRAMISU_BENCHMARKS_RAW)
FILE(STRINGS benchmarks/automatic_comm/dist_benchmark_list.txt TIRAMISU_DIST_BENCHMARKS_RAW)
FILE(STRINGS tutorials/developers_tutorial_list.txt TIRAMISU_DEVELOPERS_TUTORIALS_RAW)
FILE(STRINGS tutorials/users_tutorial_list.txt TIRAMISU_USERS_TUTORIALS_RAW)
# transforms the list of the format (program_name/program_name[tag0,tag1,..,tagn]) into a list
# containing a list of "program_name property0 property1 property2 .. propertyn"
# the list can contain as many tags as necessary
# the number of properties is fixed and is in the order given below
# current tags are : gpu, mpi, cudnn.
# current properties are : is_gpu(boolean), is_mpi(boolean), is_cudnn(boolean)
function (parse_list raw_list list_name)
set(result)
foreach(element ${raw_list})
set(tmp_result)
init_tags()
string(REGEX MATCH "^([a-zA-Z_0-9]+)(\\[([a-zA-Z0-9_]+(,[a-zA-Z0-9_]+)*)\\])?$" the_match "${element}")
if(NOT ${CMAKE_MATCH_COUNT})
message(WARNING "Could not parse: ${element}")
continue()
elseif(${CMAKE_MATCH_COUNT} GREATER 1)
STRING(REPLACE "," ";" tags ${CMAKE_MATCH_3})
parse_tags("${tags}")
endif()
set(name ${CMAKE_MATCH_1})
# The list should always have four elements (name <USE_GPU> <USE_MPI> <NUM_MPI_RANKS>)
list(APPEND tmp_result "${name}")
# Check if we need to use the GPU
if(${is_gpu})
if(${USE_GPU})
list(APPEND tmp_result "true")
else()
message(STATUS "skipping gpu tagged ${name} because USE_GPU is not set to true")
continue()
endif()
else()
list(APPEND tmp_result "false")
endif()
# Check if we need to use CUDNN
if(${is_cudnn})
if(${USE_CUDNN})
list(APPEND tmp_result "true")
else()
message(STATUS "skipping cudnn tagged ${name} because USE_CUDNN is not set to true")
continue()
endif()
else()
list(APPEND tmp_result "false")
endif()
# Check if we need to use MPI
if (${is_mpi})
if (${USE_MPI})
list(APPEND tmp_result "true")
list(APPEND tmp_result "${NUM_MPI_RANKS}")
else()
message(STATUS "skipping mpi tagged ${name} because USE_MPI is not set to true")
continue()
endif()
else ()
list(APPEND tmp_result "false")
list(APPEND tmp_result "0")
endif()
string(REPLACE ";" " " tmp_result "${tmp_result}")
list(APPEND result "${tmp_result}")
endforeach()
set("${list_name}" "${result}" PARENT_SCOPE)
endfunction()
parse_list("${TIRAMISU_BENCHMARKS_RAW}" TIRAMISU_BENCHMARKS)
parse_list("${TIRAMISU_TESTS_RAW}" TIRAMISU_TESTS)
parse_list("${TIRAMISU_DEVELOPERS_TUTORIALS_RAW}" TIRAMISU_DEVELOPERS_TUTORIALS)
parse_list("${TIRAMISU_USERS_TUTORIALS_RAW}" TIRAMISU_USERS_TUTORIALS)
parse_list("${TIRAMISU_DIST_BENCHMARKS_RAW}" TIRAMISU_DIST_BENCHMARKS)
function(link_tags name)
if (${is_gpu})
if (${USE_GPU})
target_link_libraries(${name} cuda_wrapper)
endif()
endif()
endfunction()
function(build_g name generator result)
add_executable(${name} ${generator} ${HEADER_FILES})
target_link_libraries(${name} tiramisu ${HalideLib} ${ISLLib})
target_link_libraries(${name} ${LINK_FLAGS})
link_tags(${name})
if (NOT result STREQUAL "")
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${result}")
add_custom_command(OUTPUT ${result} COMMAND ${name} WORKING_DIRECTORY ${PROJECT_DIR} DEPENDS ${name})
endif()
endfunction()
function(build_halide_g name generator result)
add_executable(${name} ${generator})
target_link_libraries(${name} ${HalideLib})
target_link_libraries(${name} ${LINK_FLAGS})
if (NOT result STREQUAL "")
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${result})
add_custom_command(OUTPUT ${result} COMMAND ${name} WORKING_DIRECTORY ${PROJECT_DIR} DEPENDS ${NAME})
endif()
endfunction()
function(build_w name objs wrapper header)
add_executable(${name} ${wrapper} ${objs} ${header})
target_link_libraries(${name} tiramisu ${HalideLib} ${ISLLib})
target_link_libraries(${name} ${LINK_FLAGS})
link_tags(${name})
endfunction()
macro(set_obj inp_obj)
if (${is_gpu})
set(obj "${inp_obj};${inp_obj}_gpu.o;${inp_obj}_cpu.o")
else()
set(obj "${inp_obj}")
endif()
endmacro()
function(parse_descriptor descriptor)
string(REPLACE " " ";" descriptor ${descriptor})
list(GET descriptor 0 id)
set(id ${id} PARENT_SCOPE)
list(GET descriptor 1 is_gpu)
set(is_gpu ${is_gpu} PARENT_SCOPE)
list(GET descriptor 2 is_mpi)
set(is_mpi ${is_mpi} PARENT_SCOPE)
list(GET descriptor 3 NUM_MPI_RANKS)
set(NUM_MPI_RANKS ${NUM_MPI_RANKS} PARENT_SCOPE)
list(GET descriptor 4 is_cudnn)
set(is_cudnn ${is_cudnn} PARENT_SCOPE)
endfunction()
if (APPLE)
set(LIB_SUF dylib)
else ()
set(LIB_SUF so)
endif ()
if (WITH_TESTS)
function(new_test descriptor)
parse_descriptor(${descriptor})
set(generator_target test_${id}_fct_generator)
set_obj(${PROJECT_BUILD}/generated_fct_test_${id}.o)
set(test_name test_${id})
build_g(${generator_target} tests/test_${id}.cpp "${obj}")
build_w(${test_name} "${obj}" tests/wrapper_test_${id}.cpp tests/wrapper_test_${id}.h)
add_test(NAME ${id}_build COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target ${test_name})
if (NOT ${is_mpi})
add_test(NAME ${id} COMMAND ${test_name} WORKING_DIRECTORY ${PROJECT_DIR})
elseif (${USE_MPI}) # This is an MPI test (sanity check that we want to use MPI though)
# configure the options so files are copied on the fly as necessary.
add_test(NAME ${id} COMMAND ${MPI_BUILD_DIR}/bin/mpirun -x LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:/tmp/ -np ${NUM_MPI_RANKS} -host ${MPI_NODES} --map-by node --oversubscribe --wdir /tmp/ --preload-files ${PROJECT_BUILD}/libtiramisu.${LIB_SUF},${PROJECT_DIR}/3rdParty/isl/.libs/libisl.${LIB_SUF} --preload-binary ${PROJECT_BUILD}/${test_name} WORKING_DIRECTORY ${PROJECT_DIR})
endif()
set_tests_properties(${id} PROPERTIES DEPENDS ${id}_build)
endfunction()
build_g(test_global tests/test_global.cpp "")
add_test(NAME global_build COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target test_global)
add_test(NAME global COMMAND test_global WORKING_DIRECTORY ${PROJECT_DIR})
set_tests_properties(global PROPERTIES DEPENDS global_build)
foreach(t ${TIRAMISU_TESTS})
new_test(${t})
endforeach()
endif() #WITH_TESTS
if (WITH_BENCHMARKS)
add_custom_target(benchmarks)
function(new_benchmark descriptor)
parse_descriptor(${descriptor})
set(tiramisu_generator_target bench_tiramisu_${id}_generator)
set(halide_generator_target bench_halide_${id}_generator)
set_obj("${PROJECT_BUILD}/generated_fct_${id}.o")
set(generated_obj_halide ${PROJECT_BUILD}/generated_fct_${id}_ref.o)
set(bench_name bench_${id})
build_g(${tiramisu_generator_target} benchmarks/halide/${id}_tiramisu.cpp "${obj}")
build_halide_g(${halide_generator_target} benchmarks/halide/${id}_ref.cpp ${generated_obj_halide})
build_w(${bench_name} "${obj};${generated_obj_halide}" benchmarks/halide/wrapper_${id}.cpp benchmarks/halide/wrapper_${id}.h)
if (NOT ${is_mpi})
add_custom_target(run_benchmark_${id} COMMAND ${bench_name} WORKING_DIRECTORY ${PROJECT_DIR})
add_custom_command(TARGET benchmarks COMMAND ${bench_name} WORKING_DIRECTORY ${PROJECT_DIR})
elseif (${USE_MPI})
# configure the options so files are copied on the fly as necessary.
add_custom_target(run_benchmark_${id} COMMAND ${MPI_BUILD_DIR}/bin/mpirun -x LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:/tmp/ -np ${NUM_MPI_RANKS} -host ${MPI_NODES} --map-by node --oversubscribe -wdir ${PROJECT_DIR} --preload-files ${PROJECT_BUILD}/libtiramisu.${LIB_SUF},${PROJECT_DIR}/3rdParty/isl/.libs/libisl.${LIB_SUF} --preload-binary ${PROJECT_BUILD}/${bench_name} WORKING_DIRECTORY ${PROJECT_DIR})
endif()
add_dependencies(run_benchmark_${id} ${bench_name})
endfunction()
foreach(b ${TIRAMISU_BENCHMARKS})
new_benchmark(${b})
endforeach()
add_custom_target(dist_benchmarks)
function(new_dist_benchmark descriptor)
parse_descriptor(${descriptor})
set(tiramisu_generator_target dist_bench_tiramisu_${id}_generator)
set(ref_generator_target dist_bench_ref_${id}_generator)
set_obj("${PROJECT_BUILD}/generated_fct_${id}.o")
set(generated_obj_ref ${PROJECT_BUILD}/generated_fct_${id}_ref.o)
set(bench_name bench_${id})
build_g(${tiramisu_generator_target} benchmarks/automatic_comm/${id}_tiramisu.cpp "${obj}")
build_g(${ref_generator_target} benchmarks/automatic_comm/${id}_ref.cpp ${generated_obj_ref})
build_w(${bench_name} "${obj};${generated_obj_ref}" benchmarks/automatic_comm/wrapper_${id}.cpp benchmarks/automatic_comm/wrapper_${id}.h)
if (NOT ${is_mpi})
add_custom_target(run_dist_benchmark_${id} COMMAND ${bench_name} WORKING_DIRECTORY ${PROJECT_DIR})
add_custom_command(TARGET dist_benchmarks COMMAND ${bench_name} WORKING_DIRECTORY ${PROJECT_DIR})
elseif (${USE_MPI})
# configure the options so files are copied on the fly as necessary.
add_custom_target(run_dist_benchmark_${id} COMMAND ${MPI_BUILD_DIR}/bin/mpirun -x LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:/tmp/ -np ${NUM_MPI_RANKS} -host ${MPI_NODES} --map-by node --oversubscribe -wdir ${PROJECT_DIR} --preload-files ${PROJECT_BUILD}/libtiramisu.${LIB_SUF},${PROJECT_DIR}/3rdParty/isl/.libs/libisl.${LIB_SUF} --preload-binary ${PROJECT_BUILD}/${bench_name} WORKING_DIRECTORY ${PROJECT_DIR})
endif()
add_dependencies(run_dist_benchmark_${id} ${bench_name})
endfunction()
foreach(b ${TIRAMISU_DIST_BENCHMARKS})
new_dist_benchmark(${b})
endforeach()
# Individual benchmarks are moved to benchmarks/CMakeLists.txt to reduce clutter
add_subdirectory(benchmarks)
endif() #WITH_BENCHMAKRS
if (WITH_DOCS)
add_custom_target(doc DEPENDS ${PROJECT_DIR}/utils/doc_generation/Doxyfile)
add_custom_command(TARGET doc COMMAND doxygen utils/doc_generation/Doxyfile WORKING_DIRECTORY ${PROJECT_DIR})
endif() #WITH_DOCS
if (WITH_TUTORIALS)
add_custom_target(tutorials)
function(new_developers_tutorial descriptor)
parse_descriptor(${descriptor})
set(generator_target developers_tutorial_${id}_fct_generator)
set_obj("${PROJECT_BUILD}/generated_fct_developers_tutorial_${id}.o")
set(tutorial_name tutorial_developers_${id})
build_g(${generator_target} tutorials/developers/tutorial_${id}/tutorial_${id}.cpp "${obj}")
build_w(${tutorial_name} "${obj}" tutorials/developers/tutorial_${id}/wrapper_tutorial_${id}.cpp tutorials/developers/tutorial_${id}/wrapper_tutorial_${id}.h)
if (NOT ${is_mpi})
add_custom_target(run_developers_tutorial_${id} COMMAND ${tutorial_name} WORKING_DIRECTORY ${PROJECT_DIR})
add_custom_command(TARGET tutorials COMMAND ${tutorial_name} WORKING_DIRECTORY ${PROJECT_DIR})
elseif (${USE_MPI}) # This is an MPI test (sanity check that we want to use MPI though)
# configure the options so files are copied on the fly as necessary.
add_custom_target(run_developers_tutorial_${id} COMMAND ${MPI_BUILD_DIR}/bin/mpirun -x LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:/tmp/ -np ${NUM_MPI_RANKS} -host ${MPI_NODES} --map-by node --oversubscribe --wdir /tmp/ --preload-files ${PROJECT_BUILD}/libtiramisu.${LIB_SUF},${PROJECT_DIR}/3rdParty/isl/.libs/libisl.${LIB_SUF} --preload-binary ${PROJECT_BUILD}/${tutorial_name} WORKING_DIRECTORY ${PROJECT_DIR})
endif()
add_dependencies(run_developers_tutorial_${id} ${tutorial_name})
endfunction()
function(new_users_tutorial descriptor)
parse_descriptor(${descriptor})
set(generator_target users_tutorial_${id}_fct_generator)
set_obj("${PROJECT_BUILD}/generated_fct_users_tutorial_${id}.o")
set(tutorial_name tutorial_users_${id})
build_g(${generator_target} tutorials/users/tutorial_${id}/tutorial_${id}.cpp "${obj}")
build_w(${tutorial_name} "${obj}" tutorials/users/tutorial_${id}/wrapper_tutorial_${id}.cpp tutorials/users/tutorial_${id}/wrapper_tutorial_${id}.h)
if (NOT ${is_mpi})
add_custom_target(run_users_tutorial_${id} COMMAND ${tutorial_name} WORKING_DIRECTORY ${PROJECT_DIR})
add_custom_command(TARGET tutorials COMMAND ${tutorial_name} WORKING_DIRECTORY ${PROJECT_DIR})
elseif (${USE_MPI}) # This is an MPI test (sanity check that we want to use MPI though)
# configure the options so files are copied on the fly as necessary.
add_custom_target(run_users_tutorial_${id} COMMAND ${MPI_BUILD_DIR}/bin/mpirun -x LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:/tmp/ -np ${NUM_MPI_RANKS} -host ${MPI_NODES} --map-by node --oversubscribe --wdir /tmp/ --preload-files ${PROJECT_BUILD}/libtiramisu.${LIB_SUF},${PROJECT_DIR}/3rdParty/isl/.libs/libisl.${LIB_SUF} --preload-binary ${PROJECT_BUILD}/${tutorial_name} WORKING_DIRECTORY ${PROJECT_DIR})
endif()
add_dependencies(run_users_tutorial_${id} ${tutorial_name})
endfunction()
foreach(t ${TIRAMISU_DEVELOPERS_TUTORIALS})
new_developers_tutorial(${t})
endforeach()
foreach(t ${TIRAMISU_USERS_TUTORIALS})
new_users_tutorial(${t})
endforeach()
endif() #WITH_TUTORIALS